Imported Upstream version 1.9.3 upstream/1.9.3
authorJinWang An <jinwang.an@samsung.com>
Tue, 27 Dec 2022 03:33:07 +0000 (12:33 +0900)
committerJinWang An <jinwang.an@samsung.com>
Tue, 27 Dec 2022 03:33:07 +0000 (12:33 +0900)
276 files changed:
.codedocs [deleted file]
.editorconfig [deleted file]
.github/ISSUE_TEMPLATE/report-a-bug-or-issue.md [deleted file]
.github/workflows/build_cmake.yml [deleted file]
.gitignore [deleted file]
CMakeLists.txt
Doxyfile
VERSION
addon/doxmlparser/CMakeLists.txt
addon/doxmlparser/LICENSE
addon/doxmlparser/doxmlparser/compound.py
addon/doxmlparser/doxmlparser/index.py
addon/doxmlparser/generateDS_post.py [new file with mode: 0755]
addon/doxyapp/doxyapp.cpp
addon/doxyparse/doxyparse.cpp
addon/doxysearch/doxysearch.cpp
addon/doxywizard/CMakeLists.txt
addon/doxywizard/config_doxyw.l
addon/doxywizard/expert.cpp
addon/doxywizard/inputbool.cpp
addon/doxywizard/inputbool.h
addon/doxywizard/inputint.h
addon/doxywizard/inputobsolete.h [new file with mode: 0644]
addon/doxywizard/inputstring.cpp
addon/doxywizard/inputstring.h
addon/doxywizard/wizard.cpp
cmake/Sanitizers/asan-wrapper [changed mode: 0644->0755]
doc/._archoverview.eps [new file with mode: 0644]
doc/._infoflow.png [new file with mode: 0644]
doc/CMakeLists.txt
doc/Doxyfile
doc/changelog.doc
doc/commands.doc
doc/customize.doc
doc/diagrams.doc
doc/docblocks.doc
doc/doxywizard_page4.png
doc/doxywizard_usage.doc
doc/emojisup.doc
doc/expert_string_filedir.png [new file with mode: 0644]
doc/htmlcmds.doc
doc/install.doc
doc/manual.sty
doc/markdown.doc
doc/perlmod.doc
doc/perlmod_tree.doc
doc/preprocessing.doc
doc/trouble.doc
doc/xmlcmds.doc
liblodepng/lodepng.cpp
libmscgen/CMakeLists.txt
libxml/CMakeLists.txt
src/CMakeLists.txt
src/cite.cpp
src/clangparser.cpp
src/clangparser.h
src/classdef.cpp
src/classdef.h
src/cmdmapper.cpp
src/cmdmapper.h
src/code.h
src/code.l
src/commentcnv.l
src/commentscan.l
src/conceptdef.cpp
src/conceptdef.h
src/config.h
src/config.xml
src/configgen.py
src/configimpl.h
src/configimpl.l
src/constexp.l
src/constexp_p.h
src/context.cpp
src/context.h
src/declinfo.l
src/defargs.l
src/definition.cpp
src/definition.h
src/definitionimpl.h
src/diagram.cpp
src/dirdef.cpp
src/dirdef.h
src/docbookgen.cpp
src/docbookgen.h
src/docbookvisitor.cpp
src/docbookvisitor.h
src/docgroup.cpp
src/docparser.cpp
src/docparser.h
src/docsets.cpp
src/doctokenizer.h
src/doctokenizer.l
src/dot.cpp
src/dotcallgraph.h
src/dotclassgraph.h
src/dotdirdeps.cpp
src/dotdirdeps.h
src/dotfilepatcher.cpp
src/dotgfxhierarchytable.cpp
src/dotgfxhierarchytable.h
src/dotgraph.cpp
src/dotgroupcollaboration.cpp
src/dotgroupcollaboration.h
src/dotincldepgraph.h
src/dotnode.cpp
src/dotnode.h
src/doxygen.cpp
src/doxygen_lex.h [new file with mode: 0644]
src/eclipsehelp.cpp
src/emoji.cpp
src/filedef.cpp
src/fileparser.cpp
src/fortrancode.l
src/fortranscanner.l
src/ftvhelp.cpp
src/groupdef.cpp
src/growbuf.h
src/htmldocvisitor.cpp
src/htmldocvisitor.h
src/htmlgen.cpp
src/htmlgen.h
src/htmlhelp.cpp
src/index.cpp
src/language.cpp
src/language.h
src/latexdocvisitor.cpp
src/latexdocvisitor.h
src/latexgen.cpp
src/latexgen.h
src/layout.cpp
src/layout.h
src/lexcode.l
src/lexscanner.l
src/mandocvisitor.cpp
src/mangen.h
src/markdown.cpp
src/markdown.h
src/memberdef.cpp
src/memberdef.h
src/membergroup.cpp
src/membergroup.h
src/memberlist.cpp
src/memberlist.h
src/message.cpp
src/msc.cpp
src/namespacedef.cpp
src/outputgen.h
src/outputlist.cpp
src/outputlist.h
src/pagedef.cpp
src/perlmodgen.cpp
src/plantuml.cpp
src/pre.l
src/printdocvisitor.h
src/pycode.l
src/pyscanner.l
src/qcstring.h
src/qhp.cpp
src/qhp.h
src/reflist.cpp
src/regex.cpp
src/rtfdocvisitor.cpp
src/rtfdocvisitor.h
src/rtfgen.cpp
src/rtfgen.h
src/rtfstyle.cpp
src/rtfstyle.h
src/scanner.l
src/searchindex.cpp
src/section.h
src/sqlcode.l
src/symbolresolver.cpp
src/tagreader.cpp
src/template.cpp
src/template.h
src/textstream.h
src/tooltip.cpp
src/translator_br.h
src/translator_cn.h
src/translator_cz.h
src/translator_de.h
src/translator_en.h
src/translator_es.h
src/translator_fr.h
src/translator_gr.h
src/translator_nl.h
src/translator_pt.h
src/translator_sv.h
src/types.h
src/util.cpp
src/util.h
src/variant.h
src/vhdlcode.l
src/vhdldocgen.cpp
src/xmlcode.l
src/xmldocvisitor.cpp
src/xmlgen.cpp
src/xmlgen.h
templates/html/bib2xhtml.pl
templates/html/doxygen.css
templates/html/dynsections_tooltips.js
templates/html/header.html
templates/html/htmlbase.tpl
templates/html/htmlclass.tpl
templates/html/htmlconcept.tpl
templates/html/htmldir.tpl
templates/html/htmlfile.tpl
templates/html/htmlmemdef.tpl
templates/html/htmlmodule.tpl
templates/html/htmlnamespace.tpl
templates/html/htmlpage.tpl
templates/html/htmlparentgroup.tpl [new file with mode: 0644]
templates/html/htmlpartofgroups.tpl [new file with mode: 0644]
templates/latex/doxygen.sty
templates/latex/header.tex
templates/xml/compound.xsd
templates/xml/doxyfile.xsd
testing/009/class_bug.xml
testing/009/class_deprecated.xml
testing/009/class_reminder.xml
testing/009/class_test.xml
testing/009/class_todo.xml
testing/011/category_integer_07_arithmetic_08.xml
testing/011/interface_integer.xml
testing/019/group___a.xml [new file with mode: 0644]
testing/019/group___b.xml [new file with mode: 0644]
testing/019/group___c.xml [new file with mode: 0644]
testing/019/group___d.xml [new file with mode: 0644]
testing/019/group__g1.xml
testing/019/group__g2.xml
testing/019/group__g3.xml
testing/019_defgroup.c
testing/021/indexpage.xml
testing/024/indexpage.xml
testing/025/class_test.xml
testing/026/class_test.xml
testing/027/struct_car.xml
testing/027/struct_object.xml
testing/027/struct_truck.xml
testing/027/struct_vehicle.xml
testing/031/indexpage.xml
testing/037/class_receiver.xml
testing/037/class_sender.xml
testing/039/class_test.xml
testing/041/class_test.xml
testing/043/mypage.xml
testing/044/struct_s.xml
testing/046/class_test.xml
testing/049/indexpage.xml
testing/055/md_055_markdown.xml
testing/057/namespacelibrary.xml
testing/057/namespacelibrary_1_1v1.xml
testing/057/namespacelibrary_1_1v2.xml
testing/058/class_class.xml
testing/058/classns2_1_1_class.xml
testing/058/classns_1_1_class.xml
testing/059/struct_n_1_1allocator__traits.xml [new file with mode: 0644]
testing/059_template.cpp [new file with mode: 0644]
testing/064/struct_foo.xml
testing/066/class_class1.xml
testing/071/namespace_a_namespace_1_1_0d0.xml
testing/074/namespacens.xml
testing/074/struct_foo.xml
testing/075/struct_foo.xml
testing/076/indexpage.xml
testing/076_emojis.cpp [changed mode: 0644->0755]
testing/078/078__xml__namespace__members__in__file__scope_8h.xml
testing/080/class_interface.xml
testing/082/namespace_n.xml
testing/083/namespace_n.xml
testing/README.txt
testing/runtests.py
vhdlparser/VhdlParserTokenManager.cc
vhdlparser/vhdl_adj.py
vhdlparser/vhdlparser.jj

diff --git a/.codedocs b/.codedocs
deleted file mode 100644 (file)
index 699b915..0000000
--- a/.codedocs
+++ /dev/null
@@ -1,3 +0,0 @@
-EXCLUDE = addon cmake doc examples jquery templates testing winbuild src/logos.cpp src/lodepng.cpp
-FILE_PATTERNS = *.h *.cpp *.md
-USE_MDFILE_AS_MAINPAGE = src/doxygen.md
diff --git a/.editorconfig b/.editorconfig
deleted file mode 100644 (file)
index ddc5adf..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# See https://editorconfig.org/ for more information.
-
-[*]
-indent_style = space
-indent_size = 2
diff --git a/.github/ISSUE_TEMPLATE/report-a-bug-or-issue.md b/.github/ISSUE_TEMPLATE/report-a-bug-or-issue.md
deleted file mode 100644 (file)
index d328fe7..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
----
-name: Report a bug or issue
-about: Create a report to help us improve doxygen
-title: ''
-labels: ''
-assignees: ''
-
----
-
-**Describe the bug**
-Describe what you see that (you think) is wrong.
-
-**Expected behavior**
-Describe what you would have expected or think is correct.
-
-**Screenshots**
-If useful, add screenshots to help explain your problem.
-
-**To Reproduce**
-Attach a self contained example that allows us to reproduce the problem.
-Such an example typically exist of some source code (can be dummy code) and a doxygen configuration file used (you can strip it using `doxygen -s -u`). After you verified the example demonstrates the problem, put it in a zip (or tarball) and attach it to the bug report. Try to avoid linking to external sources, since they might disappear in the future.
-
-**Version**
-Mention the version of doxygen used (output of `doxygen --version`) and the platform on which you run doxygen (e.g. Windows 10, 64 bit). If you run doxygen under Linux please also mention the name and version of the distribution used (output of `lsb_release -a`) and mention if you compiled doxygen yourself or that you use a binary that comes with the distribution or from the doxygen website.  
-
-**Stack trace**
-If you encounter a crash and can build doxygen from sources yourself with debug info (`-DCMAKE_BUILD_TYPE=Debug`), a stack trace can be very helpful (especially if it is not possible to capture the problem in a small example that can be shared).
-
-**Additional context**
-Add any other context about the problem here.
diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml
deleted file mode 100644 (file)
index f09a604..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-name: CMake Build for Doxygen
-
-on: [push, pull_request]
-
-jobs:
-  build:
-    name: ${{ matrix.config.name }}
-    runs-on: ${{ matrix.config.os }}
-    strategy:
-      fail-fast: false
-      matrix:
-        config:
-        - {
-            name: "Ubuntu Latest GCC Release",
-            os: ubuntu-18.04,
-            build_type: "Release", cc: "gcc", cxx: "g++",
-            build_gen: "Unix Makefiles",
-            cmake_extra_opts: "-Dbuild_search=YES -Dbuild_app=YES -Dbuild_parse=YES -Dbuild_xmlparser=YES -Duse_sqlite3=ON"
-          }
-        - {
-            name: "Ubuntu Latest GCC Debug",
-            os: ubuntu-18.04,
-            build_type: "Debug", cc: "gcc", cxx: "g++",
-            build_gen: "Unix Makefiles",
-            cmake_extra_opts: "-Dbuild_search=YES -Dbuild_app=YES -Dbuild_parse=YES -Dbuild_xmlparser=YES -Duse_sqlite3=ON"
-          }
-        - {
-            name: "Ubuntu Latest Clang Release",
-            os: ubuntu-20.04,
-            build_type: "Release", cc: "clang", cxx: "clang++",
-            build_gen: "Unix Makefiles",
-            cmake_extra_opts: "-Duse_libclang=YES -Dstatic_libclang=YES -Duse_libc++=NO -Duse_sqlite3=ON"
-          }
-        - {
-            name: "Ubuntu Latest Clang Debug",
-            os: ubuntu-20.04,
-            build_type: "Debug", cc: "clang", cxx: "clang++",
-            build_gen: "Unix Makefiles",
-            cmake_extra_opts: "-Duse_libclang=YES -Dstatic_libclang=YES -Duse_libc++=NO -Duse_sqlite3=ON"
-          }
-        - {
-            name: "macOS Latest Release",
-            os: macos-latest,
-            build_type: "Release", cc: "clang", cxx: "clang++",
-            build_gen: "Unix Makefiles"
-          }
-        - {
-            name: "macOS Latest Debug",
-            os: macos-latest,
-            build_type: "Debug", cc: "clang", cxx: "clang++",
-            build_gen: "Unix Makefiles"
-          }
-        - {
-            name: "Windows Latest MSVC Debug", 
-            os: windows-latest,
-            build_type: "Debug", cc: "cl", cxx: "cl",
-            build_gen: "NMake Makefiles"
-          }
-        - {
-            name: "Windows Latest MSVC Release", 
-            os: windows-latest,
-            build_type: "Release", cc: "cl", cxx: "cl",
-            build_gen: "NMake Makefiles"
-          }
-    steps:
-    - name: Checkout doxygen
-      uses: actions/checkout@v1
-      
-    - name: Download MikTex (Windows)
-      run: |
-        $wc = New-Object System.Net.WebClient;
-        $maxAttempts=5;
-        $attemptCount=0;
-        Do {
-          $attemptCount++;
-          Try {
-            $wc.DownloadFile("https://ctan.math.illinois.edu/systems/win32/miktex/setup/windows-x64/miktexsetup-4.1-x64.zip","miktexsetup-4.1-x64.zip")
-          } Catch [Exception] {
-            Write-Host $_.Exception | format-list -force
-          }
-        } while (((Test-Path "miktexsetup-4.1-x64.zip") -eq $false) -and ($attemptCount -le $maxAttempts))  
-      shell: pwsh
-      if: matrix.config.os == 'windows-latest'
-      
-    - name: Install libiconv (Windows)
-      uses: suisei-cn/actions-download-file@v1
-      with: 
-        url: "https://github.com/pffang/libiconv-for-Windows/releases/download/v1.16/libiconv-for-Windows_1.16.7z"
-        target: .  
-      if: matrix.config.os == 'windows-latest'
-
-    - name: Install LaTeX (Linux)
-      run: sudo apt-get install texlive texlive-latex-recommended texlive-extra-utils texlive-latex-extra texlive-font-utils
-      if: startsWith(matrix.config.os,'ubuntu-')
-
-    - name: Install LaTeX (MacOS)
-      run: |
-        brew install --cask mactex;
-        echo "/Library/TeX/texbin/" >> $GITHUB_PATH
-      if: matrix.config.os == 'macos-latest'
-    
-    - name: Install libclang (Ubuntu 20.04)
-      run: |
-        sudo apt remove llvm-8 clang-8 libclang-common-8-dev clang-format-8 libllvm8
-        sudo apt remove llvm-9 llvm-9-dev llvm-9-tools llvm-9-runtime clang-9 libclang-common-9-dev clang-format-9 libllvm9
-        #sudo apt remove llvm-10 llvm-10-dev llvm-10-tools llvm-10-runtime clang-10 clang-format-10 libclang-common-10-dev libclang-cpp10 libclang1-10 libllvm10  
-        sudo apt remove llvm-11 llvm-11-dev llvm-11-tools llvm-11-runtime clang-11 clang-format-11 libclang-common-11-dev libclang-cpp11 libclang1-11 libllvm11  
-        sudo apt remove llvm-12 llvm-12-dev llvm-12-tools llvm-12-runtime clang-12 clang-format-12 libclang-common-12-dev libclang-cpp12 libclang1-12 libllvm12  
-        sudo apt-get autoremove
-        sudo apt-get clean
-        sudo apt install libclang-common-10-dev libclang-10-dev  
-        apt list --installed | egrep '(clang|llvm)'
-        ls -d /usr/lib/llvm-*/include/
-        sudo update-alternatives --install /usr/bin/clang   clang   /usr/bin/clang-10   100
-        sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-10 100
-        ls -al /usr/bin/clang++
-        ls -al /etc/alternatives/clang++
-        which clang++
-        clang++ -v
-      if: matrix.config.os == 'ubuntu-20.04'
-    
-    - name: Install libxapian (Ubuntu 18.04)
-      run: |
-        sudo apt install libxapian-dev
-      if: matrix.config.os == 'ubuntu-18.04'
-          
-    - name: Extract MikTex zip (Windows)
-      shell: bash
-      run: |
-        unzip miktexsetup-4.1-x64.zip
-      if: matrix.config.os == 'windows-latest'
-
-    - name: Download MikTex packages (Windows)
-      shell: bash
-      run: |
-        ./miktexsetup_standalone --verbose \
-                      --local-package-repository=C:/miktex-repository \
-                      --remote-package-repository="https://ctan.math.illinois.edu/systems/win32/miktex/tm/packages/" \
-                      --package-set=essential \
-                      download
-      if: matrix.config.os == 'windows-latest'
-
-    - name: Install MikTex packages (Windows)
-      shell: bash
-      run: |
-        ./miktexsetup_standalone --local-package-repository=C:/miktex-repository \
-                      --package-set=essential \
-                      --shared \
-                      install
-      if: matrix.config.os == 'windows-latest'
-
-    - name: Setting MikTex paths (Windows)
-      shell: bash
-      run: |
-        echo "C:/Program Files/MiKTeX/miktex/bin/x64/" >> $GITHUB_PATH
-        export PATH="/c/Program Files/MiKTeX/miktex/bin/x64/:$PATH"
-        
-        echo "Configuring MiKTeX to install missing packages on the fly"
-        initexmf --admin --verbose --set-config-value='[MPM]AutoInstall=1'
-      if: matrix.config.os == 'windows-latest'
-
-    - name: Install Ghostscript (Linux)
-      run: sudo apt-get install ghostscript
-      if: startsWith(matrix.config.os,'ubuntu-')
-    
-    - name: Install Ghostscript (Windows)
-      run:
-        choco install ghostscript
-      if: matrix.config.os == 'windows-latest'
-
-    - name: Setting Ghostscript paths (Windows)
-      shell: bash
-      run: |
-        export GSpath=`find /c/Prog*/gs -name gswin\*c.exe | sed -e "s/gswin.*c.exe//"`
-        export PATH="$GSpath:$PATH"
-        export GSpath=`echo "$GSpath" | sed -e "s%/c%C:%"`
-        echo "$GSpath" >> $GITHUB_PATH
-      if: matrix.config.os == 'windows-latest'
-      
-    - name: Install xmllint (Linux)
-      run: |
-         sudo apt-get update
-         sudo apt-get install libxml2-utils
-      if: startsWith(matrix.config.os,'ubuntu-')
-
-    - name: Install xmllint (MacOS)
-      run: brew install libxml2
-      if: matrix.config.os == 'macos-latest'
-
-    - name: Install bison (MacOS)
-      run: |
-        brew install bison;
-        echo "/usr/local/opt/bison/bin" >> $GITHUB_PATH
-      if: matrix.config.os == 'macos-latest'
-    
-    - name: Install bison/flex (Windows)
-      run:
-        choco install winflexbison
-      if: matrix.config.os == 'windows-latest'
-
-    - name: Install Graphviz (Linux)
-      run: sudo apt-get install graphviz
-      if: startsWith(matrix.config.os,'ubuntu-')
-
-    - name: Install Graphviz (MacOS)
-      run: brew install graphviz
-      if: matrix.config.os == 'macos-latest'
-
-    - name: Install Graphviz (Windows)
-      run:
-        choco install graphviz.portable
-      if: matrix.config.os == 'windows-latest'
-
-#    - name: Install Perl (Windows)
-#      run:
-#        choco install activeperl
-#      if: matrix.config.os == 'windows-latest'
-
-    - name: Setup VS Environment (Windows)
-      uses: seanmiddleditch/gha-setup-vsdevenv@master
-      if: matrix.config.os == 'windows-latest'
-
-    - name: Refresh Env (Windows)
-      run:
-        refreshenv
-      if: matrix.config.os == 'windows-latest'
-    
-    - name: Install Qt
-      uses: jurplel/install-qt-action@v2
-    
-    - name: Check tool versions (Linux / MacOS)
-      shell: bash
-      run: |
-        echo "=== perl ===";
-        perl --version;
-        echo "=== python ===";
-        python --version;
-        echo "=== cmake ===";
-        cmake --version;
-        echo "=== latex ===";
-        latex --version;
-        echo "=== bibtex ===";
-        bibtex --version
-        echo "=== dvips ===";
-        dvips --version
-        echo "=== bison ===";
-        bison --version;
-        echo "=== flex ===";
-        flex --version;
-        echo "=== dot ===";
-        dot -V;
-        echo "=== ghostscript ===";
-        gs --version;
-      if: matrix.config.os != 'windows-latest'
-
-    - name: Check tool versions (Windows)
-      shell: bash
-      run: |
-        echo "=== perl ===";
-        perl --version;
-        echo "=== python ===";
-        python --version;
-        echo "=== cmake ===";
-        cmake --version;
-        echo "=== latex ===";
-        latex --version;
-        echo "=== bibtex ===";
-        bibtex --version
-        echo "=== dvips ===";
-        dvips --version
-        echo "=== bison ===";
-        win_bison --version;
-        echo "=== flex ===";
-        win_flex --version;
-        echo "=== dot ===";
-        dot -V;
-        echo "=== ghostscript ===";
-        gswin64c --version;
-      if: matrix.config.os == 'windows-latest'
-
-    - name: Configure
-      shell: cmake -P {0}
-      run: |
-        set(ENV{CC} ${{ matrix.config.cc }})
-        set(ENV{CXX} ${{ matrix.config.cxx }})
-
-        execute_process(
-          COMMAND cmake
-            -S .
-            -B build
-            -D CMAKE_BUILD_TYPE=${{ matrix.config.build_type }}
-            -G "${{ matrix.config.build_gen }}"
-            -Dbuild_doc=YES
-            -Dbuild_wizard=YES
-            ${{ matrix.config.cmake_extra_opts }}            
-          RESULT_VARIABLE result
-        )
-        if (NOT result EQUAL 0)
-          message(FATAL_ERROR "Bad exit status")
-        endif()
-
-    - name: Build
-      shell: cmake -P {0}
-      run: |
-        include(ProcessorCount)
-        ProcessorCount(N)
-        execute_process(
-          COMMAND cmake --build build --parallel ${N} 
-          RESULT_VARIABLE result
-          OUTPUT_VARIABLE output
-          ERROR_VARIABLE output
-          ECHO_OUTPUT_VARIABLE ECHO_ERROR_VARIABLE
-        )
-        if (NOT result EQUAL 0)
-          string(REGEX MATCH "FAILED:.*$" error_message "${output}")
-          string(REPLACE "\n" "%0A" error_message "${error_message}")
-          message("::error::${error_message}")
-          message(FATAL_ERROR "Build failed")
-        endif()
-
-    - name: Archive build artifacts
-      uses: actions/upload-artifact@v2
-      with:
-        name: "${{ matrix.config.name }} build artifacts"
-        path: build/bin/
-
-    - name: Run tests (Linux / MacOS)
-      shell: cmake -P {0}
-      run: |
-        include(ProcessorCount)
-        ProcessorCount(N)
-
-        set(ENV{CTEST_OUTPUT_ON_FAILURE} "ON")
-
-        execute_process(
-          COMMAND cmake --build build --target tests TEST_FLAGS="--xml --xmlxsd --xhtml --docbook --rtf"
-          RESULT_VARIABLE result
-        )
-        if (NOT result EQUAL 0)
-          message(FATAL_ERROR "Running tests failed!")
-        endif()
-      if: matrix.config.os != 'windows-latest'
-
-    - name: Run tests (Windows)
-      shell: cmake -P {0}
-      run: |
-        include(ProcessorCount)
-        ProcessorCount(N)
-
-        set(ENV{CTEST_OUTPUT_ON_FAILURE} "ON")
-
-        execute_process(
-          COMMAND cmake --build build --target tests TEST_FLAGS="--xml --xmlxsd"
-          RESULT_VARIABLE result
-        )
-        if (NOT result EQUAL 0)
-          message(FATAL_ERROR "Running tests failed!")
-        endif()
-      if: matrix.config.os == 'windows-latest'
-
-    - name: Generate documentation
-      shell: cmake -P {0}
-      run: |
-        execute_process(
-          COMMAND cmake --build build --target docs
-          RESULT_VARIABLE result
-        )
-        if (NOT result EQUAL 0)
-          message(FATAL_ERROR "Building documentation failed")
-        endif()
-      if: matrix.config.os != 'windows-latest'
diff --git a/.gitignore b/.gitignore
deleted file mode 100644 (file)
index 987aa13..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-*~
-.*sw?
-\#*
-.DS_Store
-
-*.rej
-*.orig
-
-*.pro
-/packages/rpm/doxygen.spec
-*.idb
-*.pdb
-
-/doxygen_docs
-/doxygen.tag
-/build*
-/qtools_docs
-/warnings.log
-
-tags
-
-.idea
index 251e18b..d17ffb1 100644 (file)
@@ -61,6 +61,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_CXX_EXTENSIONS ON)
 
 if (CMAKE_SYSTEM MATCHES "Darwin")
+    set(CMAKE_OSX_DEPLOYMENT_TARGET "${MACOS_VERSION_MIN}" CACHE STRING "Minimum OS X deployment version" FORCE)
     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}")
     find_library(CORESERVICES_LIB CoreServices)
@@ -82,6 +83,9 @@ if (WIN32)
         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
     endif()
 endif()
+if (CMAKE_SYSTEM_NAME MATCHES "CYGWIN")
+   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj")
+endif()
 
 if(POLICY CMP0063)
   cmake_policy(SET CMP0063 NEW)
index 09dfe45..3191475 100644 (file)
--- a/Doxyfile
+++ b/Doxyfile
@@ -221,7 +221,6 @@ PDF_HYPERLINKS         = YES
 USE_PDFLATEX           = NO
 LATEX_BATCHMODE        = NO
 LATEX_HIDE_INDICES     = NO
-LATEX_SOURCE_CODE      = NO
 LATEX_BIB_STYLE        = plain
 LATEX_TIMESTAMP        = NO
 LATEX_EMOJI_DIRECTORY  =
@@ -234,7 +233,6 @@ COMPACT_RTF            = NO
 RTF_HYPERLINKS         = NO
 RTF_STYLESHEET_FILE    =
 RTF_EXTENSIONS_FILE    =
-RTF_SOURCE_CODE        = NO
 #---------------------------------------------------------------------------
 # Configuration options related to the man page output
 #---------------------------------------------------------------------------
@@ -255,7 +253,6 @@ XML_NS_MEMB_FILE_SCOPE = NO
 #---------------------------------------------------------------------------
 GENERATE_DOCBOOK       = NO
 DOCBOOK_OUTPUT         = docbook
-DOCBOOK_PROGRAMLISTING = NO
 #---------------------------------------------------------------------------
 # Configuration options for the AutoGen Definitions output
 #---------------------------------------------------------------------------
@@ -292,7 +289,6 @@ EXTERNAL_PAGES         = YES
 #---------------------------------------------------------------------------
 # Configuration options related to the dot tool
 #---------------------------------------------------------------------------
-CLASS_DIAGRAMS         = NO
 DIA_PATH               =
 HIDE_UNDOC_RELATIONS   = YES
 HAVE_DOT               = YES
diff --git a/VERSION b/VERSION
index 8fdcf38..77fee73 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.9.2
+1.9.3
index 6ef5568..bd53041 100644 (file)
@@ -3,13 +3,19 @@ if (GENERATEDS_FOUND)
   add_custom_command(
          COMMENT "Updating index.py from index.xsd..."
          COMMAND ${GENERATEDS_EXECUTABLE} --no-dates --no-versions -f -o ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/index.py ${PROJECT_SOURCE_DIR}/templates/xml/index.xsd
-         DEPENDS ${PROJECT_SOURCE_DIR}/templates/xml/index.xsd
+         COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/addon/doxmlparser/generateDS_post.py ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/index.py ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/index_new.py
+          COMMAND ${CMAKE_COMMAND} -E remove ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/index.py
+          COMMAND ${CMAKE_COMMAND} -E rename ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/index_new.py ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/index.py
+         DEPENDS ${PROJECT_SOURCE_DIR}/templates/xml/index.xsd ${PROJECT_SOURCE_DIR}/addon/doxmlparser/generateDS_post.py
          OUTPUT  ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/index.py
   )
   add_custom_command(
          COMMENT "Updating compound.py from compound.xsd..."
          COMMAND ${GENERATEDS_EXECUTABLE} --no-dates --no-versions -f -o ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/compound.py ${PROJECT_SOURCE_DIR}/templates/xml/compound.xsd
-         DEPENDS ${PROJECT_SOURCE_DIR}/templates/xml/compound.xsd
+         COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/addon/doxmlparser/generateDS_post.py ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/compound.py ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/compound_new.py
+          COMMAND ${CMAKE_COMMAND} -E remove ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/compound.py
+          COMMAND ${CMAKE_COMMAND} -E rename ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/compound_new.py ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/compound.py
+         DEPENDS ${PROJECT_SOURCE_DIR}/templates/xml/compound.xsd ${PROJECT_SOURCE_DIR}/addon/doxmlparser/generateDS_post.py
          OUTPUT  ${PROJECT_SOURCE_DIR}/addon/doxmlparser/doxmlparser/compound.py
   )
   add_custom_target(
index d159169..ecad3f9 100644 (file)
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, 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 Lesser 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
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    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.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
+Copyright 2021 Dimitri van Heesch
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
index d15e04e..583626e 100644 (file)
@@ -3,19 +3,19 @@
 
 #
 # Generated  by generateDS.py.
-# Python 3.9.0 (default, Oct 27 2020, 14:15:17)  [Clang 12.0.0 (clang-1200.0.32.21)]
+#
 #
 # Command line options:
 #   ('--no-dates', '')
 #   ('--no-versions', '')
 #   ('-f', '')
-#   ('-o', '/Users/dimitri/doxygen.git/addon/doxmlparser/doxmlparser/compound.py')
+#   ('-o', '.../addon/doxmlparser/doxmlparser/compound.py')
 #
 # Command line arguments:
-#   /Users/dimitri/doxygen.git/templates/xml/compound.xsd
+#  .../templates/xml/compound.xsd
 #
 # Command line:
-#   /usr/local/bin/generateDS --no-dates --no-versions -f -o "/Users/dimitri/doxygen.git/addon/doxmlparser/doxmlparser/compound.py" /Users/dimitri/doxygen.git/templates/xml/compound.xsd
+#  .../generateDS --no-dates --no-versions -f -o ".../addon/doxmlparser/doxmlparser/compound.py" .../templates/xml/compound.xsd
 #
 # Current working directory (os.getcwd()):
 #   doxmlparser
@@ -175,7 +175,7 @@ except ModulenotfoundExp_ :
 try:
     from generatedssuper import GeneratedsSuper
 except ModulenotfoundExp_ as exp:
-    
+
     class GeneratedsSuper(object):
         __hash__ = object.__hash__
         tzoff_pattern = re_.compile(r'(\+|-)((0\d|1[0-3]):[0-5]\d|14:00)$')
@@ -657,8 +657,8 @@ except ModulenotfoundExp_ as exp:
                     self.gds_elementtree_node_.sourceline)
             else:
                 return ""
-    
-    
+
+
     def getSubclassFromModule_(module, class_):
         '''Get the subclass of a class from a specific module.'''
         name = class_.__name__ + 'Sub'
@@ -1007,6 +1007,7 @@ class DoxCompoundKind(str, Enum):
     PAGE='page'
     EXAMPLE='example'
     DIR='dir'
+    CONCEPT='concept'
 
 
 class DoxGraphRelation(str, Enum):
@@ -1039,6 +1040,7 @@ class DoxImageKind(str, Enum):
     LATEX='latex'
     DOCBOOK='docbook'
     RTF='rtf'
+    XML='xml'
 
 
 class DoxLanguage(str, Enum):
@@ -1076,6 +1078,14 @@ class DoxMemberKind(str, Enum):
     SERVICE='service'
 
 
+class DoxOlType(str, Enum):
+    _1='1'
+    A='a'
+    A_1='A'
+    I='i'
+    I_1='I'
+
+
 class DoxParamDir(str, Enum):
     IN='in'
     OUT='out'
@@ -1089,6 +1099,26 @@ class DoxParamListKind(str, Enum):
     TEMPLATEPARAM='templateparam'
 
 
+class DoxPlantumlEngine(str, Enum):
+    UML='uml'
+    BPM='bpm'
+    WIRE='wire'
+    DOT='dot'
+    DITAA='ditaa'
+    SALT='salt'
+    MATH='math'
+    LATEX='latex'
+    GANTT='gantt'
+    MINDMAP='mindmap'
+    WBS='wbs'
+    YAML='yaml'
+    CREOLE='creole'
+    JSON='json'
+    FLOW='flow'
+    BOARD='board'
+    GIT='git'
+
+
 class DoxProtectionKind(str, Enum):
     PUBLIC='public'
     PROTECTED='protected'
@@ -1319,7 +1349,7 @@ class compounddefType(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
     superclass = None
-    def __init__(self, id=None, kind=None, language=None, prot=None, final=None, inline=None, sealed=None, abstract=None, compoundname=None, title=None, basecompoundref=None, derivedcompoundref=None, includes=None, includedby=None, incdepgraph=None, invincdepgraph=None, innerdir=None, innerfile=None, innerclass=None, innernamespace=None, innerpage=None, innergroup=None, templateparamlist=None, sectiondef=None, tableofcontents=None, briefdescription=None, detaileddescription=None, inheritancegraph=None, collaborationgraph=None, programlisting=None, location=None, listofallmembers=None, gds_collector_=None, **kwargs_):
+    def __init__(self, id=None, kind=None, language=None, prot=None, final=None, inline=None, sealed=None, abstract=None, compoundname=None, title=None, basecompoundref=None, derivedcompoundref=None, includes=None, includedby=None, incdepgraph=None, invincdepgraph=None, innerdir=None, innerfile=None, innerclass=None, innernamespace=None, innerpage=None, innergroup=None, templateparamlist=None, sectiondef=None, tableofcontents=None, requiresclause=None, initializer=None, briefdescription=None, detaileddescription=None, inheritancegraph=None, collaborationgraph=None, programlisting=None, location=None, listofallmembers=None, gds_collector_=None, **kwargs_):
         self.gds_collector_ = gds_collector_
         self.gds_elementtree_node_ = None
         self.original_tagname_ = None
@@ -1408,6 +1438,10 @@ class compounddefType(GeneratedsSuper):
         self.sectiondef_nsprefix_ = None
         self.tableofcontents = tableofcontents
         self.tableofcontents_nsprefix_ = None
+        self.requiresclause = requiresclause
+        self.requiresclause_nsprefix_ = None
+        self.initializer = initializer
+        self.initializer_nsprefix_ = None
         self.briefdescription = briefdescription
         self.briefdescription_nsprefix_ = None
         self.detaileddescription = detaileddescription
@@ -1571,6 +1605,14 @@ class compounddefType(GeneratedsSuper):
         return self.tableofcontents
     def set_tableofcontents(self, tableofcontents):
         self.tableofcontents = tableofcontents
+    def get_requiresclause(self):
+        return self.requiresclause
+    def set_requiresclause(self, requiresclause):
+        self.requiresclause = requiresclause
+    def get_initializer(self):
+        return self.initializer
+    def set_initializer(self, initializer):
+        self.initializer = initializer
     def get_briefdescription(self):
         return self.briefdescription
     def set_briefdescription(self, briefdescription):
@@ -1639,7 +1681,7 @@ class compounddefType(GeneratedsSuper):
                 self.gds_collector_.add_message('Value "%(value)s"%(lineno)s is not of the correct base simple type (str)' % {"value": value, "lineno": lineno, })
                 return False
             value = value
-            enumerations = ['class', 'struct', 'union', 'interface', 'protocol', 'category', 'exception', 'service', 'singleton', 'module', 'type', 'file', 'namespace', 'group', 'page', 'example', 'dir']
+            enumerations = ['class', 'struct', 'union', 'interface', 'protocol', 'category', 'exception', 'service', 'singleton', 'module', 'type', 'file', 'namespace', 'group', 'page', 'example', 'dir', 'concept']
             if value not in enumerations:
                 lineno = self.gds_get_node_lineno_()
                 self.gds_collector_.add_message('Value "%(value)s"%(lineno)s does not match xsd enumeration restriction on DoxCompoundKind' % {"value" : encode_str_2_3(value), "lineno": lineno} )
@@ -1702,6 +1744,8 @@ class compounddefType(GeneratedsSuper):
             self.templateparamlist is not None or
             self.sectiondef or
             self.tableofcontents is not None or
+            self.requiresclause is not None or
+            self.initializer is not None or
             self.briefdescription is not None or
             self.detaileddescription is not None or
             self.inheritancegraph is not None or
@@ -1819,6 +1863,12 @@ class compounddefType(GeneratedsSuper):
         if self.tableofcontents is not None:
             namespaceprefix_ = self.tableofcontents_nsprefix_ + ':' if (UseCapturedNS_ and self.tableofcontents_nsprefix_) else ''
             self.tableofcontents.export(outfile, level, namespaceprefix_, namespacedef_='', name_='tableofcontents', pretty_print=pretty_print)
+        if self.requiresclause is not None:
+            namespaceprefix_ = self.requiresclause_nsprefix_ + ':' if (UseCapturedNS_ and self.requiresclause_nsprefix_) else ''
+            self.requiresclause.export(outfile, level, namespaceprefix_, namespacedef_='', name_='requiresclause', pretty_print=pretty_print)
+        if self.initializer is not None:
+            namespaceprefix_ = self.initializer_nsprefix_ + ':' if (UseCapturedNS_ and self.initializer_nsprefix_) else ''
+            self.initializer.export(outfile, level, namespaceprefix_, namespacedef_='', name_='initializer', pretty_print=pretty_print)
         if self.briefdescription is not None:
             namespaceprefix_ = self.briefdescription_nsprefix_ + ':' if (UseCapturedNS_ and self.briefdescription_nsprefix_) else ''
             self.briefdescription.export(outfile, level, namespaceprefix_, namespacedef_='', name_='briefdescription', pretty_print=pretty_print)
@@ -1979,6 +2029,16 @@ class compounddefType(GeneratedsSuper):
             obj_.build(child_, gds_collector_=gds_collector_)
             self.tableofcontents = obj_
             obj_.original_tagname_ = 'tableofcontents'
+        elif nodeName_ == 'requiresclause':
+            obj_ = linkedTextType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            self.requiresclause = obj_
+            obj_.original_tagname_ = 'requiresclause'
+        elif nodeName_ == 'initializer':
+            obj_ = linkedTextType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            self.initializer = obj_
+            obj_.original_tagname_ = 'initializer'
         elif nodeName_ == 'briefdescription':
             obj_ = descriptionType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -3364,7 +3424,7 @@ class memberdefType(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
     superclass = None
-    def __init__(self, kind=None, id=None, prot=None, static=None, strong=None, const=None, explicit=None, inline=None, refqual=None, virt=None, volatile=None, mutable=None, noexcept=None, constexpr=None, readable=None, writable=None, initonly=None, settable=None, privatesettable=None, protectedsettable=None, gettable=None, privategettable=None, protectedgettable=None, final=None, sealed=None, new=None, add=None, remove=None, raise_=None, optional=None, required=None, accessor=None, attribute=None, property=None, readonly=None, bound=None, removable=None, constrained=None, transient=None, maybevoid=None, maybedefault=None, maybeambiguous=None, templateparamlist=None, type_=None, definition=None, argsstring=None, name=None, read=None, write=None, bitfield=None, reimplements=None, reimplementedby=None, param=None, enumvalue=None, initializer=None, exceptions=None, briefdescription=None, detaileddescription=None, inbodydescription=None, location=None, references=None, referencedby=None, gds_collector_=None, **kwargs_):
+    def __init__(self, kind=None, id=None, prot=None, static=None, strong=None, const=None, explicit=None, inline=None, refqual=None, virt=None, volatile=None, mutable=None, noexcept=None, constexpr=None, readable=None, writable=None, initonly=None, settable=None, privatesettable=None, protectedsettable=None, gettable=None, privategettable=None, protectedgettable=None, final=None, sealed=None, new=None, add=None, remove=None, raise_=None, optional=None, required=None, accessor=None, attribute=None, property=None, readonly=None, bound=None, removable=None, constrained=None, transient=None, maybevoid=None, maybedefault=None, maybeambiguous=None, templateparamlist=None, type_=None, definition=None, argsstring=None, name=None, qualifiedname=None, read=None, write=None, bitfield=None, reimplements=None, reimplementedby=None, param=None, enumvalue=None, requiresclause=None, initializer=None, exceptions=None, briefdescription=None, detaileddescription=None, inbodydescription=None, location=None, references=None, referencedby=None, gds_collector_=None, **kwargs_):
         self.gds_collector_ = gds_collector_
         self.gds_elementtree_node_ = None
         self.original_tagname_ = None
@@ -3464,6 +3524,8 @@ class memberdefType(GeneratedsSuper):
         self.argsstring_nsprefix_ = None
         self.name = name
         self.name_nsprefix_ = None
+        self.qualifiedname = qualifiedname
+        self.qualifiedname_nsprefix_ = None
         self.read = read
         self.read_nsprefix_ = None
         self.write = write
@@ -3490,6 +3552,8 @@ class memberdefType(GeneratedsSuper):
         else:
             self.enumvalue = enumvalue
         self.enumvalue_nsprefix_ = None
+        self.requiresclause = requiresclause
+        self.requiresclause_nsprefix_ = None
         self.initializer = initializer
         self.initializer_nsprefix_ = None
         self.exceptions = exceptions
@@ -3547,6 +3611,10 @@ class memberdefType(GeneratedsSuper):
         return self.name
     def set_name(self, name):
         self.name = name
+    def get_qualifiedname(self):
+        return self.qualifiedname
+    def set_qualifiedname(self, qualifiedname):
+        self.qualifiedname = qualifiedname
     def get_read(self):
         return self.read
     def set_read(self, read):
@@ -3599,6 +3667,10 @@ class memberdefType(GeneratedsSuper):
         self.enumvalue.insert(index, value)
     def replace_enumvalue_at(self, index, value):
         self.enumvalue[index] = value
+    def get_requiresclause(self):
+        return self.requiresclause
+    def set_requiresclause(self, requiresclause):
+        self.requiresclause = requiresclause
     def get_initializer(self):
         return self.initializer
     def set_initializer(self, initializer):
@@ -3896,6 +3968,7 @@ class memberdefType(GeneratedsSuper):
             self.definition is not None or
             self.argsstring is not None or
             self.name is not None or
+            self.qualifiedname is not None or
             self.read is not None or
             self.write is not None or
             self.bitfield is not None or
@@ -3903,6 +3976,7 @@ class memberdefType(GeneratedsSuper):
             self.reimplementedby or
             self.param or
             self.enumvalue or
+            self.requiresclause is not None or
             self.initializer is not None or
             self.exceptions is not None or
             self.briefdescription is not None or
@@ -4088,6 +4162,10 @@ class memberdefType(GeneratedsSuper):
             namespaceprefix_ = self.name_nsprefix_ + ':' if (UseCapturedNS_ and self.name_nsprefix_) else ''
             showIndent(outfile, level, pretty_print)
             outfile.write('<%sname>%s</%sname>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(self.name), input_name='name')), namespaceprefix_ , eol_))
+        if self.qualifiedname is not None:
+            namespaceprefix_ = self.qualifiedname_nsprefix_ + ':' if (UseCapturedNS_ and self.qualifiedname_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%squalifiedname>%s</%squalifiedname>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(self.qualifiedname), input_name='qualifiedname')), namespaceprefix_ , eol_))
         if self.read is not None:
             namespaceprefix_ = self.read_nsprefix_ + ':' if (UseCapturedNS_ and self.read_nsprefix_) else ''
             showIndent(outfile, level, pretty_print)
@@ -4112,6 +4190,9 @@ class memberdefType(GeneratedsSuper):
         for enumvalue_ in self.enumvalue:
             namespaceprefix_ = self.enumvalue_nsprefix_ + ':' if (UseCapturedNS_ and self.enumvalue_nsprefix_) else ''
             enumvalue_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='enumvalue', pretty_print=pretty_print)
+        if self.requiresclause is not None:
+            namespaceprefix_ = self.requiresclause_nsprefix_ + ':' if (UseCapturedNS_ and self.requiresclause_nsprefix_) else ''
+            self.requiresclause.export(outfile, level, namespaceprefix_, namespacedef_='', name_='requiresclause', pretty_print=pretty_print)
         if self.initializer is not None:
             namespaceprefix_ = self.initializer_nsprefix_ + ':' if (UseCapturedNS_ and self.initializer_nsprefix_) else ''
             self.initializer.export(outfile, level, namespaceprefix_, namespacedef_='', name_='initializer', pretty_print=pretty_print)
@@ -4386,6 +4467,12 @@ class memberdefType(GeneratedsSuper):
             value_ = self.gds_validate_string(value_, node, 'name')
             self.name = value_
             self.name_nsprefix_ = child_.prefix
+        elif nodeName_ == 'qualifiedname':
+            value_ = child_.text
+            value_ = self.gds_parse_string(value_, node, 'qualifiedname')
+            value_ = self.gds_validate_string(value_, node, 'qualifiedname')
+            self.qualifiedname = value_
+            self.qualifiedname_nsprefix_ = child_.prefix
         elif nodeName_ == 'read':
             value_ = child_.text
             value_ = self.gds_parse_string(value_, node, 'read')
@@ -4424,6 +4511,11 @@ class memberdefType(GeneratedsSuper):
             obj_.build(child_, gds_collector_=gds_collector_)
             self.enumvalue.append(obj_)
             obj_.original_tagname_ = 'enumvalue'
+        elif nodeName_ == 'requiresclause':
+            obj_ = linkedTextType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            self.requiresclause = obj_
+            obj_.original_tagname_ = 'requiresclause'
         elif nodeName_ == 'initializer':
             obj_ = linkedTextType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -4619,6 +4711,82 @@ class argsstring(GeneratedsSuper):
 # end class argsstring
 
 
+class qualifiedname(GeneratedsSuper):
+    __hash__ = GeneratedsSuper.__hash__
+    subclass = None
+    superclass = None
+    def __init__(self, gds_collector_=None, **kwargs_):
+        self.gds_collector_ = gds_collector_
+        self.gds_elementtree_node_ = None
+        self.original_tagname_ = None
+        self.parent_object_ = kwargs_.get('parent_object_')
+        self.ns_prefix_ = None
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(
+                CurrentSubclassModule_, qualifiedname)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if qualifiedname.subclass:
+            return qualifiedname.subclass(*args_, **kwargs_)
+        else:
+            return qualifiedname(*args_, **kwargs_)
+    factory = staticmethod(factory)
+    def get_ns_prefix_(self):
+        return self.ns_prefix_
+    def set_ns_prefix_(self, ns_prefix):
+        self.ns_prefix_ = ns_prefix
+    def hasContent_(self):
+        if (
+
+        ):
+            return True
+        else:
+            return False
+    def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='qualifiedname', pretty_print=True):
+        imported_ns_def_ = GenerateDSNamespaceDefs_.get('qualifiedname')
+        if imported_ns_def_ is not None:
+            namespacedef_ = imported_ns_def_
+        if pretty_print:
+            eol_ = '\n'
+        else:
+            eol_ = ''
+        if self.original_tagname_ is not None and name_ == 'qualifiedname':
+            name_ = self.original_tagname_
+        if UseCapturedNS_ and self.ns_prefix_:
+            namespaceprefix_ = self.ns_prefix_ + ':'
+        showIndent(outfile, level, pretty_print)
+        outfile.write('<%s%s%s' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+        already_processed = set()
+        self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='qualifiedname')
+        if self.hasContent_():
+            outfile.write('>%s' % (eol_, ))
+            self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='qualifiedname', pretty_print=pretty_print)
+            outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+        else:
+            outfile.write('/>%s' % (eol_, ))
+    def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='qualifiedname'):
+        pass
+    def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='qualifiedname', fromsubclass_=False, pretty_print=True):
+        pass
+    def build(self, node, gds_collector_=None):
+        self.gds_collector_ = gds_collector_
+        if SaveElementTreeNode:
+            self.gds_elementtree_node_ = node
+        already_processed = set()
+        self.ns_prefix_ = node.prefix
+        self.buildAttributes(node, node.attrib, already_processed)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_, gds_collector_=gds_collector_)
+        return self
+    def buildAttributes(self, node, attrs, already_processed):
+        pass
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False, gds_collector_=None):
+        pass
+# end class qualifiedname
+
+
 class read(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
@@ -9228,7 +9396,7 @@ class docTitleType(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
     superclass = None
-    def __init__(self, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, del_=None, ins=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
+    def __init__(self, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, cite=None, del_=None, ins=None, details=None, summary=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
         self.gds_collector_ = gds_collector_
         self.gds_elementtree_node_ = None
         self.original_tagname_ = None
@@ -9289,6 +9457,11 @@ class docTitleType(GeneratedsSuper):
         else:
             self.small = small
         self.small_nsprefix_ = None
+        if cite is None:
+            self.cite = []
+        else:
+            self.cite = cite
+        self.cite_nsprefix_ = None
         if del_ is None:
             self.del_ = []
         else:
@@ -9299,6 +9472,16 @@ class docTitleType(GeneratedsSuper):
         else:
             self.ins = ins
         self.ins_nsprefix_ = None
+        if details is None:
+            self.details = []
+        else:
+            self.details = details
+        self.details_nsprefix_ = None
+        if summary is None:
+            self.summary = []
+        else:
+            self.summary = summary
+        self.summary_nsprefix_ = None
         if htmlonly is None:
             self.htmlonly = []
         else:
@@ -9509,6 +9692,16 @@ class docTitleType(GeneratedsSuper):
         self.small.insert(index, value)
     def replace_small_at(self, index, value):
         self.small[index] = value
+    def get_cite(self):
+        return self.cite
+    def set_cite(self, cite):
+        self.cite = cite
+    def add_cite(self, value):
+        self.cite.append(value)
+    def insert_cite_at(self, index, value):
+        self.cite.insert(index, value)
+    def replace_cite_at(self, index, value):
+        self.cite[index] = value
     def get_del(self):
         return self.del_
     def set_del(self, del_):
@@ -9529,6 +9722,26 @@ class docTitleType(GeneratedsSuper):
         self.ins.insert(index, value)
     def replace_ins_at(self, index, value):
         self.ins[index] = value
+    def get_details(self):
+        return self.details
+    def set_details(self, details):
+        self.details = details
+    def add_details(self, value):
+        self.details.append(value)
+    def insert_details_at(self, index, value):
+        self.details.insert(index, value)
+    def replace_details_at(self, index, value):
+        self.details[index] = value
+    def get_summary(self):
+        return self.summary
+    def set_summary(self, summary):
+        self.summary = summary
+    def add_summary(self, value):
+        self.summary.append(value)
+    def insert_summary_at(self, index, value):
+        self.summary.insert(index, value)
+    def replace_summary_at(self, index, value):
+        self.summary[index] = value
     def get_htmlonly(self):
         return self.htmlonly
     def set_htmlonly(self, htmlonly):
@@ -9694,8 +9907,11 @@ class docTitleType(GeneratedsSuper):
             self.superscript or
             self.center or
             self.small or
+            self.cite or
             self.del_ or
             self.ins or
+            self.details or
+            self.summary or
             self.htmlonly or
             self.manonly or
             self.xmlonly or
@@ -9783,12 +9999,21 @@ class docTitleType(GeneratedsSuper):
         for small_ in self.small:
             namespaceprefix_ = self.small_nsprefix_ + ':' if (UseCapturedNS_ and self.small_nsprefix_) else ''
             small_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='small', pretty_print=pretty_print)
+        for cite_ in self.cite:
+            namespaceprefix_ = self.cite_nsprefix_ + ':' if (UseCapturedNS_ and self.cite_nsprefix_) else ''
+            cite_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='cite', pretty_print=pretty_print)
         for del_ in self.del_:
             namespaceprefix_ = self.del__nsprefix_ + ':' if (UseCapturedNS_ and self.del__nsprefix_) else ''
             del_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='del', pretty_print=pretty_print)
         for ins_ in self.ins:
             namespaceprefix_ = self.ins_nsprefix_ + ':' if (UseCapturedNS_ and self.ins_nsprefix_) else ''
             ins_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ins', pretty_print=pretty_print)
+        for details_ in self.details:
+            namespaceprefix_ = self.details_nsprefix_ + ':' if (UseCapturedNS_ and self.details_nsprefix_) else ''
+            details_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='details', pretty_print=pretty_print)
+        for summary_ in self.summary:
+            namespaceprefix_ = self.summary_nsprefix_ + ':' if (UseCapturedNS_ and self.summary_nsprefix_) else ''
+            summary_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='summary', pretty_print=pretty_print)
         for htmlonly_ in self.htmlonly:
             namespaceprefix_ = self.htmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.htmlonly_nsprefix_) else ''
             htmlonly_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='htmlonly', pretty_print=pretty_print)
@@ -9968,6 +10193,16 @@ class docTitleType(GeneratedsSuper):
               self.add_small(obj_.value)
             elif hasattr(self, 'set_small'):
               self.set_small(obj_.value)
+        elif nodeName_ == 'cite':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'cite', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_cite'):
+              self.add_cite(obj_.value)
+            elif hasattr(self, 'set_cite'):
+              self.set_cite(obj_.value)
         elif nodeName_ == 'del':
             obj_ = docMarkupType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -9988,6 +10223,26 @@ class docTitleType(GeneratedsSuper):
               self.add_ins(obj_.value)
             elif hasattr(self, 'set_ins'):
               self.set_ins(obj_.value)
+        elif nodeName_ == 'details':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'details', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_details'):
+              self.add_details(obj_.value)
+            elif hasattr(self, 'set_details'):
+              self.set_details(obj_.value)
+        elif nodeName_ == 'summary':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'summary', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_summary'):
+              self.add_summary(obj_.value)
+            elif hasattr(self, 'set_summary'):
+              self.set_summary(obj_.value)
         elif nodeName_ == 'htmlonly':
             obj_ = docHtmlOnlyType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -10049,7 +10304,7 @@ class docTitleType(GeneratedsSuper):
             elif hasattr(self, 'set_image'):
               self.set_image(obj_.value)
         elif nodeName_ == 'dot':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'dot', obj_)
@@ -10059,7 +10314,7 @@ class docTitleType(GeneratedsSuper):
             elif hasattr(self, 'set_dot'):
               self.set_dot(obj_.value)
         elif nodeName_ == 'msc':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'msc', obj_)
@@ -10069,7 +10324,7 @@ class docTitleType(GeneratedsSuper):
             elif hasattr(self, 'set_msc'):
               self.set_msc(obj_.value)
         elif nodeName_ == 'plantuml':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docPlantumlType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'plantuml', obj_)
@@ -10139,7 +10394,7 @@ class docParaType(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
     superclass = None
-    def __init__(self, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, del_=None, ins=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, hruler=None, preformatted=None, programlisting=None, verbatim=None, indexentry=None, orderedlist=None, itemizedlist=None, simplesect=None, title=None, variablelist=None, table=None, heading=None, dotfile=None, mscfile=None, diafile=None, toclist=None, language=None, parameterlist=None, xrefsect=None, copydoc=None, blockquote=None, parblock=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
+    def __init__(self, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, cite=None, del_=None, ins=None, details=None, summary=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, hruler=None, preformatted=None, programlisting=None, verbatim=None, javadocliteral=None, javadoccode=None, indexentry=None, orderedlist=None, itemizedlist=None, simplesect=None, title=None, variablelist=None, table=None, heading=None, dotfile=None, mscfile=None, diafile=None, toclist=None, language=None, parameterlist=None, xrefsect=None, copydoc=None, blockquote=None, parblock=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
         self.gds_collector_ = gds_collector_
         self.gds_elementtree_node_ = None
         self.original_tagname_ = None
@@ -10200,6 +10455,11 @@ class docParaType(GeneratedsSuper):
         else:
             self.small = small
         self.small_nsprefix_ = None
+        if cite is None:
+            self.cite = []
+        else:
+            self.cite = cite
+        self.cite_nsprefix_ = None
         if del_ is None:
             self.del_ = []
         else:
@@ -10210,6 +10470,16 @@ class docParaType(GeneratedsSuper):
         else:
             self.ins = ins
         self.ins_nsprefix_ = None
+        if details is None:
+            self.details = []
+        else:
+            self.details = details
+        self.details_nsprefix_ = None
+        if summary is None:
+            self.summary = []
+        else:
+            self.summary = summary
+        self.summary_nsprefix_ = None
         if htmlonly is None:
             self.htmlonly = []
         else:
@@ -10305,6 +10575,16 @@ class docParaType(GeneratedsSuper):
         else:
             self.verbatim = verbatim
         self.verbatim_nsprefix_ = None
+        if javadocliteral is None:
+            self.javadocliteral = []
+        else:
+            self.javadocliteral = javadocliteral
+        self.javadocliteral_nsprefix_ = None
+        if javadoccode is None:
+            self.javadoccode = []
+        else:
+            self.javadoccode = javadoccode
+        self.javadoccode_nsprefix_ = None
         if indexentry is None:
             self.indexentry = []
         else:
@@ -10530,6 +10810,16 @@ class docParaType(GeneratedsSuper):
         self.small.insert(index, value)
     def replace_small_at(self, index, value):
         self.small[index] = value
+    def get_cite(self):
+        return self.cite
+    def set_cite(self, cite):
+        self.cite = cite
+    def add_cite(self, value):
+        self.cite.append(value)
+    def insert_cite_at(self, index, value):
+        self.cite.insert(index, value)
+    def replace_cite_at(self, index, value):
+        self.cite[index] = value
     def get_del(self):
         return self.del_
     def set_del(self, del_):
@@ -10550,6 +10840,26 @@ class docParaType(GeneratedsSuper):
         self.ins.insert(index, value)
     def replace_ins_at(self, index, value):
         self.ins[index] = value
+    def get_details(self):
+        return self.details
+    def set_details(self, details):
+        self.details = details
+    def add_details(self, value):
+        self.details.append(value)
+    def insert_details_at(self, index, value):
+        self.details.insert(index, value)
+    def replace_details_at(self, index, value):
+        self.details[index] = value
+    def get_summary(self):
+        return self.summary
+    def set_summary(self, summary):
+        self.summary = summary
+    def add_summary(self, value):
+        self.summary.append(value)
+    def insert_summary_at(self, index, value):
+        self.summary.insert(index, value)
+    def replace_summary_at(self, index, value):
+        self.summary[index] = value
     def get_htmlonly(self):
         return self.htmlonly
     def set_htmlonly(self, htmlonly):
@@ -10740,6 +11050,26 @@ class docParaType(GeneratedsSuper):
         self.verbatim.insert(index, value)
     def replace_verbatim_at(self, index, value):
         self.verbatim[index] = value
+    def get_javadocliteral(self):
+        return self.javadocliteral
+    def set_javadocliteral(self, javadocliteral):
+        self.javadocliteral = javadocliteral
+    def add_javadocliteral(self, value):
+        self.javadocliteral.append(value)
+    def insert_javadocliteral_at(self, index, value):
+        self.javadocliteral.insert(index, value)
+    def replace_javadocliteral_at(self, index, value):
+        self.javadocliteral[index] = value
+    def get_javadoccode(self):
+        return self.javadoccode
+    def set_javadoccode(self, javadoccode):
+        self.javadoccode = javadoccode
+    def add_javadoccode(self, value):
+        self.javadoccode.append(value)
+    def insert_javadoccode_at(self, index, value):
+        self.javadoccode.insert(index, value)
+    def replace_javadoccode_at(self, index, value):
+        self.javadoccode[index] = value
     def get_indexentry(self):
         return self.indexentry
     def set_indexentry(self, indexentry):
@@ -10935,8 +11265,11 @@ class docParaType(GeneratedsSuper):
             self.superscript or
             self.center or
             self.small or
+            self.cite or
             self.del_ or
             self.ins or
+            self.details or
+            self.summary or
             self.htmlonly or
             self.manonly or
             self.xmlonly or
@@ -10956,6 +11289,8 @@ class docParaType(GeneratedsSuper):
             self.preformatted or
             self.programlisting or
             self.verbatim or
+            self.javadocliteral or
+            self.javadoccode or
             self.indexentry or
             self.orderedlist or
             self.itemizedlist or
@@ -11046,12 +11381,21 @@ class docParaType(GeneratedsSuper):
         for small_ in self.small:
             namespaceprefix_ = self.small_nsprefix_ + ':' if (UseCapturedNS_ and self.small_nsprefix_) else ''
             small_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='small', pretty_print=pretty_print)
+        for cite_ in self.cite:
+            namespaceprefix_ = self.cite_nsprefix_ + ':' if (UseCapturedNS_ and self.cite_nsprefix_) else ''
+            cite_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='cite', pretty_print=pretty_print)
         for del_ in self.del_:
             namespaceprefix_ = self.del__nsprefix_ + ':' if (UseCapturedNS_ and self.del__nsprefix_) else ''
             del_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='del', pretty_print=pretty_print)
         for ins_ in self.ins:
             namespaceprefix_ = self.ins_nsprefix_ + ':' if (UseCapturedNS_ and self.ins_nsprefix_) else ''
             ins_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ins', pretty_print=pretty_print)
+        for details_ in self.details:
+            namespaceprefix_ = self.details_nsprefix_ + ':' if (UseCapturedNS_ and self.details_nsprefix_) else ''
+            details_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='details', pretty_print=pretty_print)
+        for summary_ in self.summary:
+            namespaceprefix_ = self.summary_nsprefix_ + ':' if (UseCapturedNS_ and self.summary_nsprefix_) else ''
+            summary_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='summary', pretty_print=pretty_print)
         for htmlonly_ in self.htmlonly:
             namespaceprefix_ = self.htmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.htmlonly_nsprefix_) else ''
             htmlonly_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='htmlonly', pretty_print=pretty_print)
@@ -11115,6 +11459,14 @@ class docParaType(GeneratedsSuper):
             namespaceprefix_ = self.verbatim_nsprefix_ + ':' if (UseCapturedNS_ and self.verbatim_nsprefix_) else ''
             showIndent(outfile, level, pretty_print)
             outfile.write('<%sverbatim>%s</%sverbatim>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(verbatim_), input_name='verbatim')), namespaceprefix_ , eol_))
+        for javadocliteral_ in self.javadocliteral:
+            namespaceprefix_ = self.javadocliteral_nsprefix_ + ':' if (UseCapturedNS_ and self.javadocliteral_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%sjavadocliteral>%s</%sjavadocliteral>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(javadocliteral_), input_name='javadocliteral')), namespaceprefix_ , eol_))
+        for javadoccode_ in self.javadoccode:
+            namespaceprefix_ = self.javadoccode_nsprefix_ + ':' if (UseCapturedNS_ and self.javadoccode_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%sjavadoccode>%s</%sjavadoccode>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(javadoccode_), input_name='javadoccode')), namespaceprefix_ , eol_))
         for indexentry_ in self.indexentry:
             namespaceprefix_ = self.indexentry_nsprefix_ + ':' if (UseCapturedNS_ and self.indexentry_nsprefix_) else ''
             indexentry_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='indexentry', pretty_print=pretty_print)
@@ -11298,6 +11650,16 @@ class docParaType(GeneratedsSuper):
               self.add_small(obj_.value)
             elif hasattr(self, 'set_small'):
               self.set_small(obj_.value)
+        elif nodeName_ == 'cite':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'cite', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_cite'):
+              self.add_cite(obj_.value)
+            elif hasattr(self, 'set_cite'):
+              self.set_cite(obj_.value)
         elif nodeName_ == 'del':
             obj_ = docMarkupType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -11318,6 +11680,26 @@ class docParaType(GeneratedsSuper):
               self.add_ins(obj_.value)
             elif hasattr(self, 'set_ins'):
               self.set_ins(obj_.value)
+        elif nodeName_ == 'details':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'details', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_details'):
+              self.add_details(obj_.value)
+            elif hasattr(self, 'set_details'):
+              self.set_details(obj_.value)
+        elif nodeName_ == 'summary':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'summary', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_summary'):
+              self.add_summary(obj_.value)
+            elif hasattr(self, 'set_summary'):
+              self.set_summary(obj_.value)
         elif nodeName_ == 'htmlonly':
             obj_ = docHtmlOnlyType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -11379,7 +11761,7 @@ class docParaType(GeneratedsSuper):
             elif hasattr(self, 'set_image'):
               self.set_image(obj_.value)
         elif nodeName_ == 'dot':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'dot', obj_)
@@ -11389,7 +11771,7 @@ class docParaType(GeneratedsSuper):
             elif hasattr(self, 'set_dot'):
               self.set_dot(obj_.value)
         elif nodeName_ == 'msc':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'msc', obj_)
@@ -11399,7 +11781,7 @@ class docParaType(GeneratedsSuper):
             elif hasattr(self, 'set_msc'):
               self.set_msc(obj_.value)
         elif nodeName_ == 'plantuml':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docPlantumlType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'plantuml', obj_)
@@ -11496,6 +11878,22 @@ class docParaType(GeneratedsSuper):
                 MixedContainer.TypeString, 'verbatim', valuestr_)
             self.content_.append(obj_)
             self.verbatim_nsprefix_ = child_.prefix
+        elif nodeName_ == 'javadocliteral' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'javadocliteral')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'javadocliteral')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'javadocliteral', valuestr_)
+            self.content_.append(obj_)
+            self.javadocliteral_nsprefix_ = child_.prefix
+        elif nodeName_ == 'javadoccode' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'javadoccode')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'javadoccode')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'javadoccode', valuestr_)
+            self.content_.append(obj_)
+            self.javadoccode_nsprefix_ = child_.prefix
         elif nodeName_ == 'indexentry':
             obj_ = docIndexEntryType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -11577,7 +11975,7 @@ class docParaType(GeneratedsSuper):
             elif hasattr(self, 'set_heading'):
               self.set_heading(obj_.value)
         elif nodeName_ == 'dotfile':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docImageFileType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'dotfile', obj_)
@@ -11587,7 +11985,7 @@ class docParaType(GeneratedsSuper):
             elif hasattr(self, 'set_dotfile'):
               self.set_dotfile(obj_.value)
         elif nodeName_ == 'mscfile':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docImageFileType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'mscfile', obj_)
@@ -11597,7 +11995,7 @@ class docParaType(GeneratedsSuper):
             elif hasattr(self, 'set_mscfile'):
               self.set_mscfile(obj_.value)
         elif nodeName_ == 'diafile':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docImageFileType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'diafile', obj_)
@@ -11687,7 +12085,7 @@ class docMarkupType(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
     superclass = None
-    def __init__(self, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, del_=None, ins=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, hruler=None, preformatted=None, programlisting=None, verbatim=None, indexentry=None, orderedlist=None, itemizedlist=None, simplesect=None, title=None, variablelist=None, table=None, heading=None, dotfile=None, mscfile=None, diafile=None, toclist=None, language=None, parameterlist=None, xrefsect=None, copydoc=None, blockquote=None, parblock=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
+    def __init__(self, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, cite=None, del_=None, ins=None, details=None, summary=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, hruler=None, preformatted=None, programlisting=None, verbatim=None, javadocliteral=None, javadoccode=None, indexentry=None, orderedlist=None, itemizedlist=None, simplesect=None, title=None, variablelist=None, table=None, heading=None, dotfile=None, mscfile=None, diafile=None, toclist=None, language=None, parameterlist=None, xrefsect=None, copydoc=None, blockquote=None, parblock=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
         self.gds_collector_ = gds_collector_
         self.gds_elementtree_node_ = None
         self.original_tagname_ = None
@@ -11748,6 +12146,11 @@ class docMarkupType(GeneratedsSuper):
         else:
             self.small = small
         self.small_nsprefix_ = None
+        if cite is None:
+            self.cite = []
+        else:
+            self.cite = cite
+        self.cite_nsprefix_ = None
         if del_ is None:
             self.del_ = []
         else:
@@ -11758,6 +12161,16 @@ class docMarkupType(GeneratedsSuper):
         else:
             self.ins = ins
         self.ins_nsprefix_ = None
+        if details is None:
+            self.details = []
+        else:
+            self.details = details
+        self.details_nsprefix_ = None
+        if summary is None:
+            self.summary = []
+        else:
+            self.summary = summary
+        self.summary_nsprefix_ = None
         if htmlonly is None:
             self.htmlonly = []
         else:
@@ -11853,6 +12266,16 @@ class docMarkupType(GeneratedsSuper):
         else:
             self.verbatim = verbatim
         self.verbatim_nsprefix_ = None
+        if javadocliteral is None:
+            self.javadocliteral = []
+        else:
+            self.javadocliteral = javadocliteral
+        self.javadocliteral_nsprefix_ = None
+        if javadoccode is None:
+            self.javadoccode = []
+        else:
+            self.javadoccode = javadoccode
+        self.javadoccode_nsprefix_ = None
         if indexentry is None:
             self.indexentry = []
         else:
@@ -12078,6 +12501,16 @@ class docMarkupType(GeneratedsSuper):
         self.small.insert(index, value)
     def replace_small_at(self, index, value):
         self.small[index] = value
+    def get_cite(self):
+        return self.cite
+    def set_cite(self, cite):
+        self.cite = cite
+    def add_cite(self, value):
+        self.cite.append(value)
+    def insert_cite_at(self, index, value):
+        self.cite.insert(index, value)
+    def replace_cite_at(self, index, value):
+        self.cite[index] = value
     def get_del(self):
         return self.del_
     def set_del(self, del_):
@@ -12098,6 +12531,26 @@ class docMarkupType(GeneratedsSuper):
         self.ins.insert(index, value)
     def replace_ins_at(self, index, value):
         self.ins[index] = value
+    def get_details(self):
+        return self.details
+    def set_details(self, details):
+        self.details = details
+    def add_details(self, value):
+        self.details.append(value)
+    def insert_details_at(self, index, value):
+        self.details.insert(index, value)
+    def replace_details_at(self, index, value):
+        self.details[index] = value
+    def get_summary(self):
+        return self.summary
+    def set_summary(self, summary):
+        self.summary = summary
+    def add_summary(self, value):
+        self.summary.append(value)
+    def insert_summary_at(self, index, value):
+        self.summary.insert(index, value)
+    def replace_summary_at(self, index, value):
+        self.summary[index] = value
     def get_htmlonly(self):
         return self.htmlonly
     def set_htmlonly(self, htmlonly):
@@ -12288,6 +12741,26 @@ class docMarkupType(GeneratedsSuper):
         self.verbatim.insert(index, value)
     def replace_verbatim_at(self, index, value):
         self.verbatim[index] = value
+    def get_javadocliteral(self):
+        return self.javadocliteral
+    def set_javadocliteral(self, javadocliteral):
+        self.javadocliteral = javadocliteral
+    def add_javadocliteral(self, value):
+        self.javadocliteral.append(value)
+    def insert_javadocliteral_at(self, index, value):
+        self.javadocliteral.insert(index, value)
+    def replace_javadocliteral_at(self, index, value):
+        self.javadocliteral[index] = value
+    def get_javadoccode(self):
+        return self.javadoccode
+    def set_javadoccode(self, javadoccode):
+        self.javadoccode = javadoccode
+    def add_javadoccode(self, value):
+        self.javadoccode.append(value)
+    def insert_javadoccode_at(self, index, value):
+        self.javadoccode.insert(index, value)
+    def replace_javadoccode_at(self, index, value):
+        self.javadoccode[index] = value
     def get_indexentry(self):
         return self.indexentry
     def set_indexentry(self, indexentry):
@@ -12483,8 +12956,11 @@ class docMarkupType(GeneratedsSuper):
             self.superscript or
             self.center or
             self.small or
+            self.cite or
             self.del_ or
             self.ins or
+            self.details or
+            self.summary or
             self.htmlonly or
             self.manonly or
             self.xmlonly or
@@ -12504,6 +12980,8 @@ class docMarkupType(GeneratedsSuper):
             self.preformatted or
             self.programlisting or
             self.verbatim or
+            self.javadocliteral or
+            self.javadoccode or
             self.indexentry or
             self.orderedlist or
             self.itemizedlist or
@@ -12594,12 +13072,21 @@ class docMarkupType(GeneratedsSuper):
         for small_ in self.small:
             namespaceprefix_ = self.small_nsprefix_ + ':' if (UseCapturedNS_ and self.small_nsprefix_) else ''
             small_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='small', pretty_print=pretty_print)
+        for cite_ in self.cite:
+            namespaceprefix_ = self.cite_nsprefix_ + ':' if (UseCapturedNS_ and self.cite_nsprefix_) else ''
+            cite_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='cite', pretty_print=pretty_print)
         for del_ in self.del_:
             namespaceprefix_ = self.del__nsprefix_ + ':' if (UseCapturedNS_ and self.del__nsprefix_) else ''
             del_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='del', pretty_print=pretty_print)
         for ins_ in self.ins:
             namespaceprefix_ = self.ins_nsprefix_ + ':' if (UseCapturedNS_ and self.ins_nsprefix_) else ''
             ins_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ins', pretty_print=pretty_print)
+        for details_ in self.details:
+            namespaceprefix_ = self.details_nsprefix_ + ':' if (UseCapturedNS_ and self.details_nsprefix_) else ''
+            details_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='details', pretty_print=pretty_print)
+        for summary_ in self.summary:
+            namespaceprefix_ = self.summary_nsprefix_ + ':' if (UseCapturedNS_ and self.summary_nsprefix_) else ''
+            summary_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='summary', pretty_print=pretty_print)
         for htmlonly_ in self.htmlonly:
             namespaceprefix_ = self.htmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.htmlonly_nsprefix_) else ''
             htmlonly_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='htmlonly', pretty_print=pretty_print)
@@ -12663,6 +13150,14 @@ class docMarkupType(GeneratedsSuper):
             namespaceprefix_ = self.verbatim_nsprefix_ + ':' if (UseCapturedNS_ and self.verbatim_nsprefix_) else ''
             showIndent(outfile, level, pretty_print)
             outfile.write('<%sverbatim>%s</%sverbatim>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(verbatim_), input_name='verbatim')), namespaceprefix_ , eol_))
+        for javadocliteral_ in self.javadocliteral:
+            namespaceprefix_ = self.javadocliteral_nsprefix_ + ':' if (UseCapturedNS_ and self.javadocliteral_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%sjavadocliteral>%s</%sjavadocliteral>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(javadocliteral_), input_name='javadocliteral')), namespaceprefix_ , eol_))
+        for javadoccode_ in self.javadoccode:
+            namespaceprefix_ = self.javadoccode_nsprefix_ + ':' if (UseCapturedNS_ and self.javadoccode_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%sjavadoccode>%s</%sjavadoccode>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(javadoccode_), input_name='javadoccode')), namespaceprefix_ , eol_))
         for indexentry_ in self.indexentry:
             namespaceprefix_ = self.indexentry_nsprefix_ + ':' if (UseCapturedNS_ and self.indexentry_nsprefix_) else ''
             indexentry_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='indexentry', pretty_print=pretty_print)
@@ -12846,6 +13341,16 @@ class docMarkupType(GeneratedsSuper):
               self.add_small(obj_.value)
             elif hasattr(self, 'set_small'):
               self.set_small(obj_.value)
+        elif nodeName_ == 'cite':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'cite', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_cite'):
+              self.add_cite(obj_.value)
+            elif hasattr(self, 'set_cite'):
+              self.set_cite(obj_.value)
         elif nodeName_ == 'del':
             obj_ = docMarkupType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -12866,6 +13371,26 @@ class docMarkupType(GeneratedsSuper):
               self.add_ins(obj_.value)
             elif hasattr(self, 'set_ins'):
               self.set_ins(obj_.value)
+        elif nodeName_ == 'details':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'details', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_details'):
+              self.add_details(obj_.value)
+            elif hasattr(self, 'set_details'):
+              self.set_details(obj_.value)
+        elif nodeName_ == 'summary':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'summary', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_summary'):
+              self.add_summary(obj_.value)
+            elif hasattr(self, 'set_summary'):
+              self.set_summary(obj_.value)
         elif nodeName_ == 'htmlonly':
             obj_ = docHtmlOnlyType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -12927,7 +13452,7 @@ class docMarkupType(GeneratedsSuper):
             elif hasattr(self, 'set_image'):
               self.set_image(obj_.value)
         elif nodeName_ == 'dot':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'dot', obj_)
@@ -12937,7 +13462,7 @@ class docMarkupType(GeneratedsSuper):
             elif hasattr(self, 'set_dot'):
               self.set_dot(obj_.value)
         elif nodeName_ == 'msc':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'msc', obj_)
@@ -12947,7 +13472,7 @@ class docMarkupType(GeneratedsSuper):
             elif hasattr(self, 'set_msc'):
               self.set_msc(obj_.value)
         elif nodeName_ == 'plantuml':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docPlantumlType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'plantuml', obj_)
@@ -13044,6 +13569,22 @@ class docMarkupType(GeneratedsSuper):
                 MixedContainer.TypeString, 'verbatim', valuestr_)
             self.content_.append(obj_)
             self.verbatim_nsprefix_ = child_.prefix
+        elif nodeName_ == 'javadocliteral' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'javadocliteral')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'javadocliteral')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'javadocliteral', valuestr_)
+            self.content_.append(obj_)
+            self.javadocliteral_nsprefix_ = child_.prefix
+        elif nodeName_ == 'javadoccode' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'javadoccode')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'javadoccode')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'javadoccode', valuestr_)
+            self.content_.append(obj_)
+            self.javadoccode_nsprefix_ = child_.prefix
         elif nodeName_ == 'indexentry':
             obj_ = docIndexEntryType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -13125,7 +13666,7 @@ class docMarkupType(GeneratedsSuper):
             elif hasattr(self, 'set_heading'):
               self.set_heading(obj_.value)
         elif nodeName_ == 'dotfile':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docImageFileType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'dotfile', obj_)
@@ -13135,7 +13676,7 @@ class docMarkupType(GeneratedsSuper):
             elif hasattr(self, 'set_dotfile'):
               self.set_dotfile(obj_.value)
         elif nodeName_ == 'mscfile':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docImageFileType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'mscfile', obj_)
@@ -13145,7 +13686,7 @@ class docMarkupType(GeneratedsSuper):
             elif hasattr(self, 'set_mscfile'):
               self.set_mscfile(obj_.value)
         elif nodeName_ == 'diafile':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docImageFileType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'diafile', obj_)
@@ -13235,7 +13776,7 @@ class docURLLink(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
     superclass = None
-    def __init__(self, url=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, del_=None, ins=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
+    def __init__(self, url=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, cite=None, del_=None, ins=None, details=None, summary=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
         self.gds_collector_ = gds_collector_
         self.gds_elementtree_node_ = None
         self.original_tagname_ = None
@@ -13298,6 +13839,11 @@ class docURLLink(GeneratedsSuper):
         else:
             self.small = small
         self.small_nsprefix_ = None
+        if cite is None:
+            self.cite = []
+        else:
+            self.cite = cite
+        self.cite_nsprefix_ = None
         if del_ is None:
             self.del_ = []
         else:
@@ -13308,6 +13854,16 @@ class docURLLink(GeneratedsSuper):
         else:
             self.ins = ins
         self.ins_nsprefix_ = None
+        if details is None:
+            self.details = []
+        else:
+            self.details = details
+        self.details_nsprefix_ = None
+        if summary is None:
+            self.summary = []
+        else:
+            self.summary = summary
+        self.summary_nsprefix_ = None
         if htmlonly is None:
             self.htmlonly = []
         else:
@@ -13518,6 +14074,16 @@ class docURLLink(GeneratedsSuper):
         self.small.insert(index, value)
     def replace_small_at(self, index, value):
         self.small[index] = value
+    def get_cite(self):
+        return self.cite
+    def set_cite(self, cite):
+        self.cite = cite
+    def add_cite(self, value):
+        self.cite.append(value)
+    def insert_cite_at(self, index, value):
+        self.cite.insert(index, value)
+    def replace_cite_at(self, index, value):
+        self.cite[index] = value
     def get_del(self):
         return self.del_
     def set_del(self, del_):
@@ -13538,6 +14104,26 @@ class docURLLink(GeneratedsSuper):
         self.ins.insert(index, value)
     def replace_ins_at(self, index, value):
         self.ins[index] = value
+    def get_details(self):
+        return self.details
+    def set_details(self, details):
+        self.details = details
+    def add_details(self, value):
+        self.details.append(value)
+    def insert_details_at(self, index, value):
+        self.details.insert(index, value)
+    def replace_details_at(self, index, value):
+        self.details[index] = value
+    def get_summary(self):
+        return self.summary
+    def set_summary(self, summary):
+        self.summary = summary
+    def add_summary(self, value):
+        self.summary.append(value)
+    def insert_summary_at(self, index, value):
+        self.summary.insert(index, value)
+    def replace_summary_at(self, index, value):
+        self.summary[index] = value
     def get_htmlonly(self):
         return self.htmlonly
     def set_htmlonly(self, htmlonly):
@@ -13707,8 +14293,11 @@ class docURLLink(GeneratedsSuper):
             self.superscript or
             self.center or
             self.small or
+            self.cite or
             self.del_ or
             self.ins or
+            self.details or
+            self.summary or
             self.htmlonly or
             self.manonly or
             self.xmlonly or
@@ -13798,12 +14387,21 @@ class docURLLink(GeneratedsSuper):
         for small_ in self.small:
             namespaceprefix_ = self.small_nsprefix_ + ':' if (UseCapturedNS_ and self.small_nsprefix_) else ''
             small_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='small', pretty_print=pretty_print)
+        for cite_ in self.cite:
+            namespaceprefix_ = self.cite_nsprefix_ + ':' if (UseCapturedNS_ and self.cite_nsprefix_) else ''
+            cite_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='cite', pretty_print=pretty_print)
         for del_ in self.del_:
             namespaceprefix_ = self.del__nsprefix_ + ':' if (UseCapturedNS_ and self.del__nsprefix_) else ''
             del_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='del', pretty_print=pretty_print)
         for ins_ in self.ins:
             namespaceprefix_ = self.ins_nsprefix_ + ':' if (UseCapturedNS_ and self.ins_nsprefix_) else ''
             ins_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ins', pretty_print=pretty_print)
+        for details_ in self.details:
+            namespaceprefix_ = self.details_nsprefix_ + ':' if (UseCapturedNS_ and self.details_nsprefix_) else ''
+            details_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='details', pretty_print=pretty_print)
+        for summary_ in self.summary:
+            namespaceprefix_ = self.summary_nsprefix_ + ':' if (UseCapturedNS_ and self.summary_nsprefix_) else ''
+            summary_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='summary', pretty_print=pretty_print)
         for htmlonly_ in self.htmlonly:
             namespaceprefix_ = self.htmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.htmlonly_nsprefix_) else ''
             htmlonly_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='htmlonly', pretty_print=pretty_print)
@@ -13986,6 +14584,16 @@ class docURLLink(GeneratedsSuper):
               self.add_small(obj_.value)
             elif hasattr(self, 'set_small'):
               self.set_small(obj_.value)
+        elif nodeName_ == 'cite':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'cite', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_cite'):
+              self.add_cite(obj_.value)
+            elif hasattr(self, 'set_cite'):
+              self.set_cite(obj_.value)
         elif nodeName_ == 'del':
             obj_ = docMarkupType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -14006,6 +14614,26 @@ class docURLLink(GeneratedsSuper):
               self.add_ins(obj_.value)
             elif hasattr(self, 'set_ins'):
               self.set_ins(obj_.value)
+        elif nodeName_ == 'details':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'details', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_details'):
+              self.add_details(obj_.value)
+            elif hasattr(self, 'set_details'):
+              self.set_details(obj_.value)
+        elif nodeName_ == 'summary':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'summary', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_summary'):
+              self.add_summary(obj_.value)
+            elif hasattr(self, 'set_summary'):
+              self.set_summary(obj_.value)
         elif nodeName_ == 'htmlonly':
             obj_ = docHtmlOnlyType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -14067,7 +14695,7 @@ class docURLLink(GeneratedsSuper):
             elif hasattr(self, 'set_image'):
               self.set_image(obj_.value)
         elif nodeName_ == 'dot':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'dot', obj_)
@@ -14077,7 +14705,7 @@ class docURLLink(GeneratedsSuper):
             elif hasattr(self, 'set_dot'):
               self.set_dot(obj_.value)
         elif nodeName_ == 'msc':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'msc', obj_)
@@ -14087,7 +14715,7 @@ class docURLLink(GeneratedsSuper):
             elif hasattr(self, 'set_msc'):
               self.set_msc(obj_.value)
         elif nodeName_ == 'plantuml':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docPlantumlType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'plantuml', obj_)
@@ -14483,12 +15111,16 @@ class docListType(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
     superclass = None
-    def __init__(self, listitem=None, gds_collector_=None, **kwargs_):
+    def __init__(self, type_=None, start=None, listitem=None, gds_collector_=None, **kwargs_):
         self.gds_collector_ = gds_collector_
         self.gds_elementtree_node_ = None
         self.original_tagname_ = None
         self.parent_object_ = kwargs_.get('parent_object_')
         self.ns_prefix_ = None
+        self.type_ = _cast(None, type_)
+        self.type__nsprefix_ = None
+        self.start = _cast(int, start)
+        self.start_nsprefix_ = None
         if listitem is None:
             self.listitem = []
         else:
@@ -14519,6 +15151,27 @@ class docListType(GeneratedsSuper):
         self.listitem.insert(index, value)
     def replace_listitem_at(self, index, value):
         self.listitem[index] = value
+    def get_type(self):
+        return self.type_
+    def set_type(self, type_):
+        self.type_ = type_
+    def get_start(self):
+        return self.start
+    def set_start(self, start):
+        self.start = start
+    def validate_DoxOlType(self, value):
+        # Validate type DoxOlType, a restriction on xsd:string.
+        if value is not None and Validate_simpletypes_ and self.gds_collector_ is not None:
+            if not isinstance(value, str):
+                lineno = self.gds_get_node_lineno_()
+                self.gds_collector_.add_message('Value "%(value)s"%(lineno)s is not of the correct base simple type (str)' % {"value": value, "lineno": lineno, })
+                return False
+            value = value
+            enumerations = ['1', 'a', 'A', 'i', 'I']
+            if value not in enumerations:
+                lineno = self.gds_get_node_lineno_()
+                self.gds_collector_.add_message('Value "%(value)s"%(lineno)s does not match xsd enumeration restriction on DoxOlType' % {"value" : encode_str_2_3(value), "lineno": lineno} )
+                result = False
     def hasContent_(self):
         if (
             self.listitem
@@ -14550,7 +15203,12 @@ class docListType(GeneratedsSuper):
         else:
             outfile.write('/>%s' % (eol_, ))
     def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='docListType'):
-        pass
+        if self.type_ is not None and 'type_' not in already_processed:
+            already_processed.add('type_')
+            outfile.write(' type=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.type_), input_name='type')), ))
+        if self.start is not None and 'start' not in already_processed:
+            already_processed.add('start')
+            outfile.write(' start="%s"' % self.gds_format_integer(self.start, input_name='start'))
     def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='docListType', fromsubclass_=False, pretty_print=True):
         if pretty_print:
             eol_ = '\n'
@@ -14571,7 +15229,15 @@ class docListType(GeneratedsSuper):
             self.buildChildren(child, node, nodeName_, gds_collector_=gds_collector_)
         return self
     def buildAttributes(self, node, attrs, already_processed):
-        pass
+        value = find_attr_value_('type', node)
+        if value is not None and 'type' not in already_processed:
+            already_processed.add('type')
+            self.type_ = value
+            self.validate_DoxOlType(self.type_)    # validate type DoxOlType
+        value = find_attr_value_('start', node)
+        if value is not None and 'start' not in already_processed:
+            already_processed.add('start')
+            self.start = self.gds_parse_integer(value, node, 'start')
     def buildChildren(self, child_, node, nodeName_, fromsubclass_=False, gds_collector_=None):
         if nodeName_ == 'listitem':
             obj_ = docListItemType.factory(parent_object_=self)
@@ -14585,12 +15251,14 @@ class docListItemType(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
     superclass = None
-    def __init__(self, para=None, gds_collector_=None, **kwargs_):
+    def __init__(self, value=None, para=None, gds_collector_=None, **kwargs_):
         self.gds_collector_ = gds_collector_
         self.gds_elementtree_node_ = None
         self.original_tagname_ = None
         self.parent_object_ = kwargs_.get('parent_object_')
         self.ns_prefix_ = None
+        self.value = _cast(int, value)
+        self.value_nsprefix_ = None
         if para is None:
             self.para = []
         else:
@@ -14621,6 +15289,10 @@ class docListItemType(GeneratedsSuper):
         self.para.insert(index, value)
     def replace_para_at(self, index, value):
         self.para[index] = value
+    def get_value(self):
+        return self.value
+    def set_value(self, value):
+        self.value = value
     def hasContent_(self):
         if (
             self.para
@@ -14652,7 +15324,9 @@ class docListItemType(GeneratedsSuper):
         else:
             outfile.write('/>%s' % (eol_, ))
     def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='docListItemType'):
-        pass
+        if self.value is not None and 'value' not in already_processed:
+            already_processed.add('value')
+            outfile.write(' value="%s"' % self.gds_format_integer(self.value, input_name='value'))
     def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='docListItemType', fromsubclass_=False, pretty_print=True):
         if pretty_print:
             eol_ = '\n'
@@ -14673,7 +15347,10 @@ class docListItemType(GeneratedsSuper):
             self.buildChildren(child, node, nodeName_, gds_collector_=gds_collector_)
         return self
     def buildAttributes(self, node, attrs, already_processed):
-        pass
+        value = find_attr_value_('value', node)
+        if value is not None and 'value' not in already_processed:
+            already_processed.add('value')
+            self.value = self.gds_parse_integer(value, node, 'value')
     def buildChildren(self, child_, node, nodeName_, fromsubclass_=False, gds_collector_=None):
         if nodeName_ == 'para':
             obj_ = docParaType.factory(parent_object_=self)
@@ -15048,7 +15725,7 @@ class docRefTextType(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
     superclass = None
-    def __init__(self, refid=None, kindref=None, external=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, del_=None, ins=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
+    def __init__(self, refid=None, kindref=None, external=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, cite=None, del_=None, ins=None, details=None, summary=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
         self.gds_collector_ = gds_collector_
         self.gds_elementtree_node_ = None
         self.original_tagname_ = None
@@ -15115,6 +15792,11 @@ class docRefTextType(GeneratedsSuper):
         else:
             self.small = small
         self.small_nsprefix_ = None
+        if cite is None:
+            self.cite = []
+        else:
+            self.cite = cite
+        self.cite_nsprefix_ = None
         if del_ is None:
             self.del_ = []
         else:
@@ -15125,6 +15807,16 @@ class docRefTextType(GeneratedsSuper):
         else:
             self.ins = ins
         self.ins_nsprefix_ = None
+        if details is None:
+            self.details = []
+        else:
+            self.details = details
+        self.details_nsprefix_ = None
+        if summary is None:
+            self.summary = []
+        else:
+            self.summary = summary
+        self.summary_nsprefix_ = None
         if htmlonly is None:
             self.htmlonly = []
         else:
@@ -15335,6 +16027,16 @@ class docRefTextType(GeneratedsSuper):
         self.small.insert(index, value)
     def replace_small_at(self, index, value):
         self.small[index] = value
+    def get_cite(self):
+        return self.cite
+    def set_cite(self, cite):
+        self.cite = cite
+    def add_cite(self, value):
+        self.cite.append(value)
+    def insert_cite_at(self, index, value):
+        self.cite.insert(index, value)
+    def replace_cite_at(self, index, value):
+        self.cite[index] = value
     def get_del(self):
         return self.del_
     def set_del(self, del_):
@@ -15355,6 +16057,26 @@ class docRefTextType(GeneratedsSuper):
         self.ins.insert(index, value)
     def replace_ins_at(self, index, value):
         self.ins[index] = value
+    def get_details(self):
+        return self.details
+    def set_details(self, details):
+        self.details = details
+    def add_details(self, value):
+        self.details.append(value)
+    def insert_details_at(self, index, value):
+        self.details.insert(index, value)
+    def replace_details_at(self, index, value):
+        self.details[index] = value
+    def get_summary(self):
+        return self.summary
+    def set_summary(self, summary):
+        self.summary = summary
+    def add_summary(self, value):
+        self.summary.append(value)
+    def insert_summary_at(self, index, value):
+        self.summary.insert(index, value)
+    def replace_summary_at(self, index, value):
+        self.summary[index] = value
     def get_htmlonly(self):
         return self.htmlonly
     def set_htmlonly(self, htmlonly):
@@ -15545,8 +16267,11 @@ class docRefTextType(GeneratedsSuper):
             self.superscript or
             self.center or
             self.small or
+            self.cite or
             self.del_ or
             self.ins or
+            self.details or
+            self.summary or
             self.htmlonly or
             self.manonly or
             self.xmlonly or
@@ -15642,12 +16367,21 @@ class docRefTextType(GeneratedsSuper):
         for small_ in self.small:
             namespaceprefix_ = self.small_nsprefix_ + ':' if (UseCapturedNS_ and self.small_nsprefix_) else ''
             small_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='small', pretty_print=pretty_print)
+        for cite_ in self.cite:
+            namespaceprefix_ = self.cite_nsprefix_ + ':' if (UseCapturedNS_ and self.cite_nsprefix_) else ''
+            cite_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='cite', pretty_print=pretty_print)
         for del_ in self.del_:
             namespaceprefix_ = self.del__nsprefix_ + ':' if (UseCapturedNS_ and self.del__nsprefix_) else ''
             del_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='del', pretty_print=pretty_print)
         for ins_ in self.ins:
             namespaceprefix_ = self.ins_nsprefix_ + ':' if (UseCapturedNS_ and self.ins_nsprefix_) else ''
             ins_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ins', pretty_print=pretty_print)
+        for details_ in self.details:
+            namespaceprefix_ = self.details_nsprefix_ + ':' if (UseCapturedNS_ and self.details_nsprefix_) else ''
+            details_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='details', pretty_print=pretty_print)
+        for summary_ in self.summary:
+            namespaceprefix_ = self.summary_nsprefix_ + ':' if (UseCapturedNS_ and self.summary_nsprefix_) else ''
+            summary_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='summary', pretty_print=pretty_print)
         for htmlonly_ in self.htmlonly:
             namespaceprefix_ = self.htmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.htmlonly_nsprefix_) else ''
             htmlonly_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='htmlonly', pretty_print=pretty_print)
@@ -15839,6 +16573,16 @@ class docRefTextType(GeneratedsSuper):
               self.add_small(obj_.value)
             elif hasattr(self, 'set_small'):
               self.set_small(obj_.value)
+        elif nodeName_ == 'cite':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'cite', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_cite'):
+              self.add_cite(obj_.value)
+            elif hasattr(self, 'set_cite'):
+              self.set_cite(obj_.value)
         elif nodeName_ == 'del':
             obj_ = docMarkupType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -15859,6 +16603,26 @@ class docRefTextType(GeneratedsSuper):
               self.add_ins(obj_.value)
             elif hasattr(self, 'set_ins'):
               self.set_ins(obj_.value)
+        elif nodeName_ == 'details':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'details', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_details'):
+              self.add_details(obj_.value)
+            elif hasattr(self, 'set_details'):
+              self.set_details(obj_.value)
+        elif nodeName_ == 'summary':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'summary', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_summary'):
+              self.add_summary(obj_.value)
+            elif hasattr(self, 'set_summary'):
+              self.set_summary(obj_.value)
         elif nodeName_ == 'htmlonly':
             obj_ = docHtmlOnlyType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -15920,7 +16684,7 @@ class docRefTextType(GeneratedsSuper):
             elif hasattr(self, 'set_image'):
               self.set_image(obj_.value)
         elif nodeName_ == 'dot':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'dot', obj_)
@@ -15930,7 +16694,7 @@ class docRefTextType(GeneratedsSuper):
             elif hasattr(self, 'set_dot'):
               self.set_dot(obj_.value)
         elif nodeName_ == 'msc':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'msc', obj_)
@@ -15940,7 +16704,7 @@ class docRefTextType(GeneratedsSuper):
             elif hasattr(self, 'set_msc'):
               self.set_msc(obj_.value)
         elif nodeName_ == 'plantuml':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docPlantumlType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'plantuml', obj_)
@@ -16537,12 +17301,14 @@ class docCaptionType(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
     superclass = None
-    def __init__(self, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, del_=None, ins=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
+    def __init__(self, id=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, cite=None, del_=None, ins=None, details=None, summary=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
         self.gds_collector_ = gds_collector_
         self.gds_elementtree_node_ = None
         self.original_tagname_ = None
         self.parent_object_ = kwargs_.get('parent_object_')
         self.ns_prefix_ = None
+        self.id = _cast(None, id)
+        self.id_nsprefix_ = None
         if ulink is None:
             self.ulink = []
         else:
@@ -16598,6 +17364,11 @@ class docCaptionType(GeneratedsSuper):
         else:
             self.small = small
         self.small_nsprefix_ = None
+        if cite is None:
+            self.cite = []
+        else:
+            self.cite = cite
+        self.cite_nsprefix_ = None
         if del_ is None:
             self.del_ = []
         else:
@@ -16608,6 +17379,16 @@ class docCaptionType(GeneratedsSuper):
         else:
             self.ins = ins
         self.ins_nsprefix_ = None
+        if details is None:
+            self.details = []
+        else:
+            self.details = details
+        self.details_nsprefix_ = None
+        if summary is None:
+            self.summary = []
+        else:
+            self.summary = summary
+        self.summary_nsprefix_ = None
         if htmlonly is None:
             self.htmlonly = []
         else:
@@ -16818,6 +17599,16 @@ class docCaptionType(GeneratedsSuper):
         self.small.insert(index, value)
     def replace_small_at(self, index, value):
         self.small[index] = value
+    def get_cite(self):
+        return self.cite
+    def set_cite(self, cite):
+        self.cite = cite
+    def add_cite(self, value):
+        self.cite.append(value)
+    def insert_cite_at(self, index, value):
+        self.cite.insert(index, value)
+    def replace_cite_at(self, index, value):
+        self.cite[index] = value
     def get_del(self):
         return self.del_
     def set_del(self, del_):
@@ -16838,6 +17629,26 @@ class docCaptionType(GeneratedsSuper):
         self.ins.insert(index, value)
     def replace_ins_at(self, index, value):
         self.ins[index] = value
+    def get_details(self):
+        return self.details
+    def set_details(self, details):
+        self.details = details
+    def add_details(self, value):
+        self.details.append(value)
+    def insert_details_at(self, index, value):
+        self.details.insert(index, value)
+    def replace_details_at(self, index, value):
+        self.details[index] = value
+    def get_summary(self):
+        return self.summary
+    def set_summary(self, summary):
+        self.summary = summary
+    def add_summary(self, value):
+        self.summary.append(value)
+    def insert_summary_at(self, index, value):
+        self.summary.insert(index, value)
+    def replace_summary_at(self, index, value):
+        self.summary[index] = value
     def get_htmlonly(self):
         return self.htmlonly
     def set_htmlonly(self, htmlonly):
@@ -16988,8 +17799,12 @@ class docCaptionType(GeneratedsSuper):
         self.linebreak.insert(index, value)
     def replace_linebreak_at(self, index, value):
         self.linebreak[index] = value
-    def get_valueOf_(self): return self.valueOf_
-    def set_valueOf_(self, valueOf_): self.valueOf_ = valueOf_
+    def get_id(self):
+        return self.id
+    def set_id(self, id):
+        self.id = id
+    def get_valueOf_(self): return self.valueOf_
+    def set_valueOf_(self, valueOf_): self.valueOf_ = valueOf_
     def hasContent_(self):
         if (
             self.ulink or
@@ -17003,8 +17818,11 @@ class docCaptionType(GeneratedsSuper):
             self.superscript or
             self.center or
             self.small or
+            self.cite or
             self.del_ or
             self.ins or
+            self.details or
+            self.summary or
             self.htmlonly or
             self.manonly or
             self.xmlonly or
@@ -17050,7 +17868,9 @@ class docCaptionType(GeneratedsSuper):
         else:
             outfile.write('/>%s' % (eol_, ))
     def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='docCaptionType'):
-        pass
+        if self.id is not None and 'id' not in already_processed:
+            already_processed.add('id')
+            outfile.write(' id=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.id), input_name='id')), ))
     def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='docCaptionType', fromsubclass_=False, pretty_print=True):
         if not fromsubclass_:
             for item_ in self.content_:
@@ -17092,12 +17912,21 @@ class docCaptionType(GeneratedsSuper):
         for small_ in self.small:
             namespaceprefix_ = self.small_nsprefix_ + ':' if (UseCapturedNS_ and self.small_nsprefix_) else ''
             small_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='small', pretty_print=pretty_print)
+        for cite_ in self.cite:
+            namespaceprefix_ = self.cite_nsprefix_ + ':' if (UseCapturedNS_ and self.cite_nsprefix_) else ''
+            cite_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='cite', pretty_print=pretty_print)
         for del_ in self.del_:
             namespaceprefix_ = self.del__nsprefix_ + ':' if (UseCapturedNS_ and self.del__nsprefix_) else ''
             del_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='del', pretty_print=pretty_print)
         for ins_ in self.ins:
             namespaceprefix_ = self.ins_nsprefix_ + ':' if (UseCapturedNS_ and self.ins_nsprefix_) else ''
             ins_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ins', pretty_print=pretty_print)
+        for details_ in self.details:
+            namespaceprefix_ = self.details_nsprefix_ + ':' if (UseCapturedNS_ and self.details_nsprefix_) else ''
+            details_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='details', pretty_print=pretty_print)
+        for summary_ in self.summary:
+            namespaceprefix_ = self.summary_nsprefix_ + ':' if (UseCapturedNS_ and self.summary_nsprefix_) else ''
+            summary_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='summary', pretty_print=pretty_print)
         for htmlonly_ in self.htmlonly:
             namespaceprefix_ = self.htmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.htmlonly_nsprefix_) else ''
             htmlonly_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='htmlonly', pretty_print=pretty_print)
@@ -17165,7 +17994,10 @@ class docCaptionType(GeneratedsSuper):
             self.buildChildren(child, node, nodeName_, gds_collector_=gds_collector_)
         return self
     def buildAttributes(self, node, attrs, already_processed):
-        pass
+        value = find_attr_value_('id', node)
+        if value is not None and 'id' not in already_processed:
+            already_processed.add('id')
+            self.id = value
     def buildChildren(self, child_, node, nodeName_, fromsubclass_=False, gds_collector_=None):
         if nodeName_ == 'ulink':
             obj_ = docURLLink.factory(parent_object_=self)
@@ -17277,6 +18109,16 @@ class docCaptionType(GeneratedsSuper):
               self.add_small(obj_.value)
             elif hasattr(self, 'set_small'):
               self.set_small(obj_.value)
+        elif nodeName_ == 'cite':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'cite', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_cite'):
+              self.add_cite(obj_.value)
+            elif hasattr(self, 'set_cite'):
+              self.set_cite(obj_.value)
         elif nodeName_ == 'del':
             obj_ = docMarkupType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -17297,6 +18139,26 @@ class docCaptionType(GeneratedsSuper):
               self.add_ins(obj_.value)
             elif hasattr(self, 'set_ins'):
               self.set_ins(obj_.value)
+        elif nodeName_ == 'details':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'details', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_details'):
+              self.add_details(obj_.value)
+            elif hasattr(self, 'set_details'):
+              self.set_details(obj_.value)
+        elif nodeName_ == 'summary':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'summary', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_summary'):
+              self.add_summary(obj_.value)
+            elif hasattr(self, 'set_summary'):
+              self.set_summary(obj_.value)
         elif nodeName_ == 'htmlonly':
             obj_ = docHtmlOnlyType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -17358,7 +18220,7 @@ class docCaptionType(GeneratedsSuper):
             elif hasattr(self, 'set_image'):
               self.set_image(obj_.value)
         elif nodeName_ == 'dot':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'dot', obj_)
@@ -17368,7 +18230,7 @@ class docCaptionType(GeneratedsSuper):
             elif hasattr(self, 'set_dot'):
               self.set_dot(obj_.value)
         elif nodeName_ == 'msc':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'msc', obj_)
@@ -17378,7 +18240,7 @@ class docCaptionType(GeneratedsSuper):
             elif hasattr(self, 'set_msc'):
               self.set_msc(obj_.value)
         elif nodeName_ == 'plantuml':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docPlantumlType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'plantuml', obj_)
@@ -17448,7 +18310,7 @@ class docHeadingType(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
     superclass = None
-    def __init__(self, level=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, del_=None, ins=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
+    def __init__(self, level=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, cite=None, del_=None, ins=None, details=None, summary=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
         self.gds_collector_ = gds_collector_
         self.gds_elementtree_node_ = None
         self.original_tagname_ = None
@@ -17511,6 +18373,11 @@ class docHeadingType(GeneratedsSuper):
         else:
             self.small = small
         self.small_nsprefix_ = None
+        if cite is None:
+            self.cite = []
+        else:
+            self.cite = cite
+        self.cite_nsprefix_ = None
         if del_ is None:
             self.del_ = []
         else:
@@ -17521,6 +18388,16 @@ class docHeadingType(GeneratedsSuper):
         else:
             self.ins = ins
         self.ins_nsprefix_ = None
+        if details is None:
+            self.details = []
+        else:
+            self.details = details
+        self.details_nsprefix_ = None
+        if summary is None:
+            self.summary = []
+        else:
+            self.summary = summary
+        self.summary_nsprefix_ = None
         if htmlonly is None:
             self.htmlonly = []
         else:
@@ -17731,6 +18608,16 @@ class docHeadingType(GeneratedsSuper):
         self.small.insert(index, value)
     def replace_small_at(self, index, value):
         self.small[index] = value
+    def get_cite(self):
+        return self.cite
+    def set_cite(self, cite):
+        self.cite = cite
+    def add_cite(self, value):
+        self.cite.append(value)
+    def insert_cite_at(self, index, value):
+        self.cite.insert(index, value)
+    def replace_cite_at(self, index, value):
+        self.cite[index] = value
     def get_del(self):
         return self.del_
     def set_del(self, del_):
@@ -17751,6 +18638,26 @@ class docHeadingType(GeneratedsSuper):
         self.ins.insert(index, value)
     def replace_ins_at(self, index, value):
         self.ins[index] = value
+    def get_details(self):
+        return self.details
+    def set_details(self, details):
+        self.details = details
+    def add_details(self, value):
+        self.details.append(value)
+    def insert_details_at(self, index, value):
+        self.details.insert(index, value)
+    def replace_details_at(self, index, value):
+        self.details[index] = value
+    def get_summary(self):
+        return self.summary
+    def set_summary(self, summary):
+        self.summary = summary
+    def add_summary(self, value):
+        self.summary.append(value)
+    def insert_summary_at(self, index, value):
+        self.summary.insert(index, value)
+    def replace_summary_at(self, index, value):
+        self.summary[index] = value
     def get_htmlonly(self):
         return self.htmlonly
     def set_htmlonly(self, htmlonly):
@@ -17920,8 +18827,11 @@ class docHeadingType(GeneratedsSuper):
             self.superscript or
             self.center or
             self.small or
+            self.cite or
             self.del_ or
             self.ins or
+            self.details or
+            self.summary or
             self.htmlonly or
             self.manonly or
             self.xmlonly or
@@ -18011,12 +18921,21 @@ class docHeadingType(GeneratedsSuper):
         for small_ in self.small:
             namespaceprefix_ = self.small_nsprefix_ + ':' if (UseCapturedNS_ and self.small_nsprefix_) else ''
             small_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='small', pretty_print=pretty_print)
+        for cite_ in self.cite:
+            namespaceprefix_ = self.cite_nsprefix_ + ':' if (UseCapturedNS_ and self.cite_nsprefix_) else ''
+            cite_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='cite', pretty_print=pretty_print)
         for del_ in self.del_:
             namespaceprefix_ = self.del__nsprefix_ + ':' if (UseCapturedNS_ and self.del__nsprefix_) else ''
             del_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='del', pretty_print=pretty_print)
         for ins_ in self.ins:
             namespaceprefix_ = self.ins_nsprefix_ + ':' if (UseCapturedNS_ and self.ins_nsprefix_) else ''
             ins_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ins', pretty_print=pretty_print)
+        for details_ in self.details:
+            namespaceprefix_ = self.details_nsprefix_ + ':' if (UseCapturedNS_ and self.details_nsprefix_) else ''
+            details_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='details', pretty_print=pretty_print)
+        for summary_ in self.summary:
+            namespaceprefix_ = self.summary_nsprefix_ + ':' if (UseCapturedNS_ and self.summary_nsprefix_) else ''
+            summary_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='summary', pretty_print=pretty_print)
         for htmlonly_ in self.htmlonly:
             namespaceprefix_ = self.htmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.htmlonly_nsprefix_) else ''
             htmlonly_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='htmlonly', pretty_print=pretty_print)
@@ -18199,6 +19118,16 @@ class docHeadingType(GeneratedsSuper):
               self.add_small(obj_.value)
             elif hasattr(self, 'set_small'):
               self.set_small(obj_.value)
+        elif nodeName_ == 'cite':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'cite', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_cite'):
+              self.add_cite(obj_.value)
+            elif hasattr(self, 'set_cite'):
+              self.set_cite(obj_.value)
         elif nodeName_ == 'del':
             obj_ = docMarkupType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -18219,6 +19148,26 @@ class docHeadingType(GeneratedsSuper):
               self.add_ins(obj_.value)
             elif hasattr(self, 'set_ins'):
               self.set_ins(obj_.value)
+        elif nodeName_ == 'details':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'details', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_details'):
+              self.add_details(obj_.value)
+            elif hasattr(self, 'set_details'):
+              self.set_details(obj_.value)
+        elif nodeName_ == 'summary':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'summary', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_summary'):
+              self.add_summary(obj_.value)
+            elif hasattr(self, 'set_summary'):
+              self.set_summary(obj_.value)
         elif nodeName_ == 'htmlonly':
             obj_ = docHtmlOnlyType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -18280,7 +19229,7 @@ class docHeadingType(GeneratedsSuper):
             elif hasattr(self, 'set_image'):
               self.set_image(obj_.value)
         elif nodeName_ == 'dot':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'dot', obj_)
@@ -18290,7 +19239,7 @@ class docHeadingType(GeneratedsSuper):
             elif hasattr(self, 'set_dot'):
               self.set_dot(obj_.value)
         elif nodeName_ == 'msc':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'msc', obj_)
@@ -18300,7 +19249,7 @@ class docHeadingType(GeneratedsSuper):
             elif hasattr(self, 'set_msc'):
               self.set_msc(obj_.value)
         elif nodeName_ == 'plantuml':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docPlantumlType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'plantuml', obj_)
@@ -18370,7 +19319,7 @@ class docImageType(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
     superclass = None
-    def __init__(self, type_=None, name=None, width=None, height=None, alt=None, inline=None, caption=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, del_=None, ins=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
+    def __init__(self, type_=None, name=None, width=None, height=None, alt=None, inline=None, caption=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, cite=None, del_=None, ins=None, details=None, summary=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
         self.gds_collector_ = gds_collector_
         self.gds_elementtree_node_ = None
         self.original_tagname_ = None
@@ -18445,6 +19394,11 @@ class docImageType(GeneratedsSuper):
         else:
             self.small = small
         self.small_nsprefix_ = None
+        if cite is None:
+            self.cite = []
+        else:
+            self.cite = cite
+        self.cite_nsprefix_ = None
         if del_ is None:
             self.del_ = []
         else:
@@ -18455,6 +19409,16 @@ class docImageType(GeneratedsSuper):
         else:
             self.ins = ins
         self.ins_nsprefix_ = None
+        if details is None:
+            self.details = []
+        else:
+            self.details = details
+        self.details_nsprefix_ = None
+        if summary is None:
+            self.summary = []
+        else:
+            self.summary = summary
+        self.summary_nsprefix_ = None
         if htmlonly is None:
             self.htmlonly = []
         else:
@@ -18665,6 +19629,16 @@ class docImageType(GeneratedsSuper):
         self.small.insert(index, value)
     def replace_small_at(self, index, value):
         self.small[index] = value
+    def get_cite(self):
+        return self.cite
+    def set_cite(self, cite):
+        self.cite = cite
+    def add_cite(self, value):
+        self.cite.append(value)
+    def insert_cite_at(self, index, value):
+        self.cite.insert(index, value)
+    def replace_cite_at(self, index, value):
+        self.cite[index] = value
     def get_del(self):
         return self.del_
     def set_del(self, del_):
@@ -18685,6 +19659,26 @@ class docImageType(GeneratedsSuper):
         self.ins.insert(index, value)
     def replace_ins_at(self, index, value):
         self.ins[index] = value
+    def get_details(self):
+        return self.details
+    def set_details(self, details):
+        self.details = details
+    def add_details(self, value):
+        self.details.append(value)
+    def insert_details_at(self, index, value):
+        self.details.insert(index, value)
+    def replace_details_at(self, index, value):
+        self.details[index] = value
+    def get_summary(self):
+        return self.summary
+    def set_summary(self, summary):
+        self.summary = summary
+    def add_summary(self, value):
+        self.summary.append(value)
+    def insert_summary_at(self, index, value):
+        self.summary.insert(index, value)
+    def replace_summary_at(self, index, value):
+        self.summary[index] = value
     def get_htmlonly(self):
         return self.htmlonly
     def set_htmlonly(self, htmlonly):
@@ -18873,7 +19867,7 @@ class docImageType(GeneratedsSuper):
                 self.gds_collector_.add_message('Value "%(value)s"%(lineno)s is not of the correct base simple type (str)' % {"value": value, "lineno": lineno, })
                 return False
             value = value
-            enumerations = ['html', 'latex', 'docbook', 'rtf']
+            enumerations = ['html', 'latex', 'docbook', 'rtf', 'xml']
             if value not in enumerations:
                 lineno = self.gds_get_node_lineno_()
                 self.gds_collector_.add_message('Value "%(value)s"%(lineno)s does not match xsd enumeration restriction on DoxImageKind' % {"value" : encode_str_2_3(value), "lineno": lineno} )
@@ -18904,8 +19898,11 @@ class docImageType(GeneratedsSuper):
             self.superscript or
             self.center or
             self.small or
+            self.cite or
             self.del_ or
             self.ins or
+            self.details or
+            self.summary or
             self.htmlonly or
             self.manonly or
             self.xmlonly or
@@ -19013,12 +20010,21 @@ class docImageType(GeneratedsSuper):
         for small_ in self.small:
             namespaceprefix_ = self.small_nsprefix_ + ':' if (UseCapturedNS_ and self.small_nsprefix_) else ''
             small_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='small', pretty_print=pretty_print)
+        for cite_ in self.cite:
+            namespaceprefix_ = self.cite_nsprefix_ + ':' if (UseCapturedNS_ and self.cite_nsprefix_) else ''
+            cite_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='cite', pretty_print=pretty_print)
         for del_ in self.del_:
             namespaceprefix_ = self.del__nsprefix_ + ':' if (UseCapturedNS_ and self.del__nsprefix_) else ''
             del_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='del', pretty_print=pretty_print)
         for ins_ in self.ins:
             namespaceprefix_ = self.ins_nsprefix_ + ':' if (UseCapturedNS_ and self.ins_nsprefix_) else ''
             ins_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ins', pretty_print=pretty_print)
+        for details_ in self.details:
+            namespaceprefix_ = self.details_nsprefix_ + ':' if (UseCapturedNS_ and self.details_nsprefix_) else ''
+            details_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='details', pretty_print=pretty_print)
+        for summary_ in self.summary:
+            namespaceprefix_ = self.summary_nsprefix_ + ':' if (UseCapturedNS_ and self.summary_nsprefix_) else ''
+            summary_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='summary', pretty_print=pretty_print)
         for htmlonly_ in self.htmlonly:
             namespaceprefix_ = self.htmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.htmlonly_nsprefix_) else ''
             htmlonly_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='htmlonly', pretty_print=pretty_print)
@@ -19227,6 +20233,16 @@ class docImageType(GeneratedsSuper):
               self.add_small(obj_.value)
             elif hasattr(self, 'set_small'):
               self.set_small(obj_.value)
+        elif nodeName_ == 'cite':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'cite', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_cite'):
+              self.add_cite(obj_.value)
+            elif hasattr(self, 'set_cite'):
+              self.set_cite(obj_.value)
         elif nodeName_ == 'del':
             obj_ = docMarkupType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -19247,6 +20263,26 @@ class docImageType(GeneratedsSuper):
               self.add_ins(obj_.value)
             elif hasattr(self, 'set_ins'):
               self.set_ins(obj_.value)
+        elif nodeName_ == 'details':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'details', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_details'):
+              self.add_details(obj_.value)
+            elif hasattr(self, 'set_details'):
+              self.set_details(obj_.value)
+        elif nodeName_ == 'summary':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'summary', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_summary'):
+              self.add_summary(obj_.value)
+            elif hasattr(self, 'set_summary'):
+              self.set_summary(obj_.value)
         elif nodeName_ == 'htmlonly':
             obj_ = docHtmlOnlyType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -19308,7 +20344,7 @@ class docImageType(GeneratedsSuper):
             elif hasattr(self, 'set_image'):
               self.set_image(obj_.value)
         elif nodeName_ == 'dot':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'dot', obj_)
@@ -19318,7 +20354,7 @@ class docImageType(GeneratedsSuper):
             elif hasattr(self, 'set_dot'):
               self.set_dot(obj_.value)
         elif nodeName_ == 'msc':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'msc', obj_)
@@ -19328,7 +20364,7 @@ class docImageType(GeneratedsSuper):
             elif hasattr(self, 'set_msc'):
               self.set_msc(obj_.value)
         elif nodeName_ == 'plantuml':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docPlantumlType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'plantuml', obj_)
@@ -19394,18 +20430,24 @@ class docImageType(GeneratedsSuper):
 # end class docImageType
 
 
-class docTocItemType(GeneratedsSuper):
+class docDotMscType(GeneratedsSuper):
     __hash__ = GeneratedsSuper.__hash__
     subclass = None
     superclass = None
-    def __init__(self, id=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, del_=None, ins=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
+    def __init__(self, name=None, width=None, height=None, caption=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, cite=None, del_=None, ins=None, details=None, summary=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
         self.gds_collector_ = gds_collector_
         self.gds_elementtree_node_ = None
         self.original_tagname_ = None
         self.parent_object_ = kwargs_.get('parent_object_')
         self.ns_prefix_ = None
-        self.id = _cast(None, id)
-        self.id_nsprefix_ = None
+        self.name = _cast(None, name)
+        self.name_nsprefix_ = None
+        self.width = _cast(None, width)
+        self.width_nsprefix_ = None
+        self.height = _cast(None, height)
+        self.height_nsprefix_ = None
+        self.caption = _cast(None, caption)
+        self.caption_nsprefix_ = None
         if ulink is None:
             self.ulink = []
         else:
@@ -19461,6 +20503,11 @@ class docTocItemType(GeneratedsSuper):
         else:
             self.small = small
         self.small_nsprefix_ = None
+        if cite is None:
+            self.cite = []
+        else:
+            self.cite = cite
+        self.cite_nsprefix_ = None
         if del_ is None:
             self.del_ = []
         else:
@@ -19471,6 +20518,16 @@ class docTocItemType(GeneratedsSuper):
         else:
             self.ins = ins
         self.ins_nsprefix_ = None
+        if details is None:
+            self.details = []
+        else:
+            self.details = details
+        self.details_nsprefix_ = None
+        if summary is None:
+            self.summary = []
+        else:
+            self.summary = summary
+        self.summary_nsprefix_ = None
         if htmlonly is None:
             self.htmlonly = []
         else:
@@ -19559,13 +20616,13 @@ class docTocItemType(GeneratedsSuper):
     def factory(*args_, **kwargs_):
         if CurrentSubclassModule_ is not None:
             subclass = getSubclassFromModule_(
-                CurrentSubclassModule_, docTocItemType)
+                CurrentSubclassModule_, docDotMscType)
             if subclass is not None:
                 return subclass(*args_, **kwargs_)
-        if docTocItemType.subclass:
-            return docTocItemType.subclass(*args_, **kwargs_)
+        if docDotMscType.subclass:
+            return docDotMscType.subclass(*args_, **kwargs_)
         else:
-            return docTocItemType(*args_, **kwargs_)
+            return docDotMscType(*args_, **kwargs_)
     factory = staticmethod(factory)
     def get_ns_prefix_(self):
         return self.ns_prefix_
@@ -19681,6 +20738,16 @@ class docTocItemType(GeneratedsSuper):
         self.small.insert(index, value)
     def replace_small_at(self, index, value):
         self.small[index] = value
+    def get_cite(self):
+        return self.cite
+    def set_cite(self, cite):
+        self.cite = cite
+    def add_cite(self, value):
+        self.cite.append(value)
+    def insert_cite_at(self, index, value):
+        self.cite.insert(index, value)
+    def replace_cite_at(self, index, value):
+        self.cite[index] = value
     def get_del(self):
         return self.del_
     def set_del(self, del_):
@@ -19701,6 +20768,26 @@ class docTocItemType(GeneratedsSuper):
         self.ins.insert(index, value)
     def replace_ins_at(self, index, value):
         self.ins[index] = value
+    def get_details(self):
+        return self.details
+    def set_details(self, details):
+        self.details = details
+    def add_details(self, value):
+        self.details.append(value)
+    def insert_details_at(self, index, value):
+        self.details.insert(index, value)
+    def replace_details_at(self, index, value):
+        self.details[index] = value
+    def get_summary(self):
+        return self.summary
+    def set_summary(self, summary):
+        self.summary = summary
+    def add_summary(self, value):
+        self.summary.append(value)
+    def insert_summary_at(self, index, value):
+        self.summary.insert(index, value)
+    def replace_summary_at(self, index, value):
+        self.summary[index] = value
     def get_htmlonly(self):
         return self.htmlonly
     def set_htmlonly(self, htmlonly):
@@ -19851,10 +20938,22 @@ class docTocItemType(GeneratedsSuper):
         self.linebreak.insert(index, value)
     def replace_linebreak_at(self, index, value):
         self.linebreak[index] = value
-    def get_id(self):
-        return self.id
-    def set_id(self, id):
-        self.id = id
+    def get_name(self):
+        return self.name
+    def set_name(self, name):
+        self.name = name
+    def get_width(self):
+        return self.width
+    def set_width(self, width):
+        self.width = width
+    def get_height(self):
+        return self.height
+    def set_height(self, height):
+        self.height = height
+    def get_caption(self):
+        return self.caption
+    def set_caption(self, caption):
+        self.caption = caption
     def get_valueOf_(self): return self.valueOf_
     def set_valueOf_(self, valueOf_): self.valueOf_ = valueOf_
     def hasContent_(self):
@@ -19870,8 +20969,11 @@ class docTocItemType(GeneratedsSuper):
             self.superscript or
             self.center or
             self.small or
+            self.cite or
             self.del_ or
             self.ins or
+            self.details or
+            self.summary or
             self.htmlonly or
             self.manonly or
             self.xmlonly or
@@ -19893,34 +20995,43 @@ class docTocItemType(GeneratedsSuper):
             return True
         else:
             return False
-    def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='docTocItemType', pretty_print=True):
-        imported_ns_def_ = GenerateDSNamespaceDefs_.get('docTocItemType')
+    def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='docDotMscType', pretty_print=True):
+        imported_ns_def_ = GenerateDSNamespaceDefs_.get('docDotMscType')
         if imported_ns_def_ is not None:
             namespacedef_ = imported_ns_def_
         if pretty_print:
             eol_ = '\n'
         else:
             eol_ = ''
-        if self.original_tagname_ is not None and name_ == 'docTocItemType':
+        if self.original_tagname_ is not None and name_ == 'docDotMscType':
             name_ = self.original_tagname_
         if UseCapturedNS_ and self.ns_prefix_:
             namespaceprefix_ = self.ns_prefix_ + ':'
         showIndent(outfile, level, pretty_print)
         outfile.write('<%s%s%s' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
         already_processed = set()
-        self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='docTocItemType')
+        self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='docDotMscType')
         if self.hasContent_():
             outfile.write('>%s' % (eol_, ))
-            self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='docTocItemType', pretty_print=pretty_print)
+            self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='docDotMscType', pretty_print=pretty_print)
             showIndent(outfile, level, pretty_print)
             outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
         else:
             outfile.write('/>%s' % (eol_, ))
-    def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='docTocItemType'):
-        if self.id is not None and 'id' not in already_processed:
-            already_processed.add('id')
-            outfile.write(' id=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.id), input_name='id')), ))
-    def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='docTocItemType', fromsubclass_=False, pretty_print=True):
+    def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='docDotMscType'):
+        if self.name is not None and 'name' not in already_processed:
+            already_processed.add('name')
+            outfile.write(' name=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.name), input_name='name')), ))
+        if self.width is not None and 'width' not in already_processed:
+            already_processed.add('width')
+            outfile.write(' width=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.width), input_name='width')), ))
+        if self.height is not None and 'height' not in already_processed:
+            already_processed.add('height')
+            outfile.write(' height=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.height), input_name='height')), ))
+        if self.caption is not None and 'caption' not in already_processed:
+            already_processed.add('caption')
+            outfile.write(' caption=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.caption), input_name='caption')), ))
+    def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='docDotMscType', fromsubclass_=False, pretty_print=True):
         if not fromsubclass_:
             for item_ in self.content_:
                 item_.export(outfile, level, item_.name, namespaceprefix_, pretty_print=pretty_print)
@@ -19961,12 +21072,21 @@ class docTocItemType(GeneratedsSuper):
         for small_ in self.small:
             namespaceprefix_ = self.small_nsprefix_ + ':' if (UseCapturedNS_ and self.small_nsprefix_) else ''
             small_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='small', pretty_print=pretty_print)
+        for cite_ in self.cite:
+            namespaceprefix_ = self.cite_nsprefix_ + ':' if (UseCapturedNS_ and self.cite_nsprefix_) else ''
+            cite_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='cite', pretty_print=pretty_print)
         for del_ in self.del_:
             namespaceprefix_ = self.del__nsprefix_ + ':' if (UseCapturedNS_ and self.del__nsprefix_) else ''
             del_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='del', pretty_print=pretty_print)
         for ins_ in self.ins:
             namespaceprefix_ = self.ins_nsprefix_ + ':' if (UseCapturedNS_ and self.ins_nsprefix_) else ''
             ins_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ins', pretty_print=pretty_print)
+        for details_ in self.details:
+            namespaceprefix_ = self.details_nsprefix_ + ':' if (UseCapturedNS_ and self.details_nsprefix_) else ''
+            details_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='details', pretty_print=pretty_print)
+        for summary_ in self.summary:
+            namespaceprefix_ = self.summary_nsprefix_ + ':' if (UseCapturedNS_ and self.summary_nsprefix_) else ''
+            summary_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='summary', pretty_print=pretty_print)
         for htmlonly_ in self.htmlonly:
             namespaceprefix_ = self.htmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.htmlonly_nsprefix_) else ''
             htmlonly_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='htmlonly', pretty_print=pretty_print)
@@ -20034,10 +21154,22 @@ class docTocItemType(GeneratedsSuper):
             self.buildChildren(child, node, nodeName_, gds_collector_=gds_collector_)
         return self
     def buildAttributes(self, node, attrs, already_processed):
-        value = find_attr_value_('id', node)
-        if value is not None and 'id' not in already_processed:
-            already_processed.add('id')
-            self.id = value
+        value = find_attr_value_('name', node)
+        if value is not None and 'name' not in already_processed:
+            already_processed.add('name')
+            self.name = value
+        value = find_attr_value_('width', node)
+        if value is not None and 'width' not in already_processed:
+            already_processed.add('width')
+            self.width = value
+        value = find_attr_value_('height', node)
+        if value is not None and 'height' not in already_processed:
+            already_processed.add('height')
+            self.height = value
+        value = find_attr_value_('caption', node)
+        if value is not None and 'caption' not in already_processed:
+            already_processed.add('caption')
+            self.caption = value
     def buildChildren(self, child_, node, nodeName_, fromsubclass_=False, gds_collector_=None):
         if nodeName_ == 'ulink':
             obj_ = docURLLink.factory(parent_object_=self)
@@ -20149,6 +21281,16 @@ class docTocItemType(GeneratedsSuper):
               self.add_small(obj_.value)
             elif hasattr(self, 'set_small'):
               self.set_small(obj_.value)
+        elif nodeName_ == 'cite':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'cite', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_cite'):
+              self.add_cite(obj_.value)
+            elif hasattr(self, 'set_cite'):
+              self.set_cite(obj_.value)
         elif nodeName_ == 'del':
             obj_ = docMarkupType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -20169,6 +21311,26 @@ class docTocItemType(GeneratedsSuper):
               self.add_ins(obj_.value)
             elif hasattr(self, 'set_ins'):
               self.set_ins(obj_.value)
+        elif nodeName_ == 'details':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'details', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_details'):
+              self.add_details(obj_.value)
+            elif hasattr(self, 'set_details'):
+              self.set_details(obj_.value)
+        elif nodeName_ == 'summary':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'summary', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_summary'):
+              self.add_summary(obj_.value)
+            elif hasattr(self, 'set_summary'):
+              self.set_summary(obj_.value)
         elif nodeName_ == 'htmlonly':
             obj_ = docHtmlOnlyType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
@@ -20230,7 +21392,7 @@ class docTocItemType(GeneratedsSuper):
             elif hasattr(self, 'set_image'):
               self.set_image(obj_.value)
         elif nodeName_ == 'dot':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'dot', obj_)
@@ -20240,7 +21402,7 @@ class docTocItemType(GeneratedsSuper):
             elif hasattr(self, 'set_dot'):
               self.set_dot(obj_.value)
         elif nodeName_ == 'msc':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docDotMscType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'msc', obj_)
@@ -20250,7 +21412,3126 @@ class docTocItemType(GeneratedsSuper):
             elif hasattr(self, 'set_msc'):
               self.set_msc(obj_.value)
         elif nodeName_ == 'plantuml':
-            obj_ = docImageType.factory(parent_object_=self)
+            obj_ = docPlantumlType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'plantuml', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_plantuml'):
+              self.add_plantuml(obj_.value)
+            elif hasattr(self, 'set_plantuml'):
+              self.set_plantuml(obj_.value)
+        elif nodeName_ == 'anchor':
+            obj_ = docAnchorType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'anchor', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_anchor'):
+              self.add_anchor(obj_.value)
+            elif hasattr(self, 'set_anchor'):
+              self.set_anchor(obj_.value)
+        elif nodeName_ == 'formula':
+            obj_ = docFormulaType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'formula', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_formula'):
+              self.add_formula(obj_.value)
+            elif hasattr(self, 'set_formula'):
+              self.set_formula(obj_.value)
+        elif nodeName_ == 'ref':
+            obj_ = docRefTextType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'ref', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_ref'):
+              self.add_ref(obj_.value)
+            elif hasattr(self, 'set_ref'):
+              self.set_ref(obj_.value)
+        elif nodeName_ == 'emoji':
+            obj_ = docEmojiType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'emoji', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_emoji'):
+              self.add_emoji(obj_.value)
+            elif hasattr(self, 'set_emoji'):
+              self.set_emoji(obj_.value)
+        elif nodeName_ == 'linebreak':
+            obj_ = docEmptyType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'linebreak', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_linebreak'):
+              self.add_linebreak(obj_.value)
+            elif hasattr(self, 'set_linebreak'):
+              self.set_linebreak(obj_.value)
+        if not fromsubclass_ and child_.tail is not None:
+            obj_ = self.mixedclass_(MixedContainer.CategoryText,
+                MixedContainer.TypeNone, '', child_.tail)
+            self.content_.append(obj_)
+# end class docDotMscType
+
+
+class docImageFileType(GeneratedsSuper):
+    __hash__ = GeneratedsSuper.__hash__
+    subclass = None
+    superclass = None
+    def __init__(self, name=None, width=None, height=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, cite=None, del_=None, ins=None, details=None, summary=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
+        self.gds_collector_ = gds_collector_
+        self.gds_elementtree_node_ = None
+        self.original_tagname_ = None
+        self.parent_object_ = kwargs_.get('parent_object_')
+        self.ns_prefix_ = None
+        self.name = _cast(None, name)
+        self.name_nsprefix_ = None
+        self.width = _cast(None, width)
+        self.width_nsprefix_ = None
+        self.height = _cast(None, height)
+        self.height_nsprefix_ = None
+        if ulink is None:
+            self.ulink = []
+        else:
+            self.ulink = ulink
+        self.ulink_nsprefix_ = None
+        if bold is None:
+            self.bold = []
+        else:
+            self.bold = bold
+        self.bold_nsprefix_ = None
+        if s is None:
+            self.s = []
+        else:
+            self.s = s
+        self.s_nsprefix_ = None
+        if strike is None:
+            self.strike = []
+        else:
+            self.strike = strike
+        self.strike_nsprefix_ = None
+        if underline is None:
+            self.underline = []
+        else:
+            self.underline = underline
+        self.underline_nsprefix_ = None
+        if emphasis is None:
+            self.emphasis = []
+        else:
+            self.emphasis = emphasis
+        self.emphasis_nsprefix_ = None
+        if computeroutput is None:
+            self.computeroutput = []
+        else:
+            self.computeroutput = computeroutput
+        self.computeroutput_nsprefix_ = None
+        if subscript is None:
+            self.subscript = []
+        else:
+            self.subscript = subscript
+        self.subscript_nsprefix_ = None
+        if superscript is None:
+            self.superscript = []
+        else:
+            self.superscript = superscript
+        self.superscript_nsprefix_ = None
+        if center is None:
+            self.center = []
+        else:
+            self.center = center
+        self.center_nsprefix_ = None
+        if small is None:
+            self.small = []
+        else:
+            self.small = small
+        self.small_nsprefix_ = None
+        if cite is None:
+            self.cite = []
+        else:
+            self.cite = cite
+        self.cite_nsprefix_ = None
+        if del_ is None:
+            self.del_ = []
+        else:
+            self.del_ = del_
+        self.del__nsprefix_ = None
+        if ins is None:
+            self.ins = []
+        else:
+            self.ins = ins
+        self.ins_nsprefix_ = None
+        if details is None:
+            self.details = []
+        else:
+            self.details = details
+        self.details_nsprefix_ = None
+        if summary is None:
+            self.summary = []
+        else:
+            self.summary = summary
+        self.summary_nsprefix_ = None
+        if htmlonly is None:
+            self.htmlonly = []
+        else:
+            self.htmlonly = htmlonly
+        self.htmlonly_nsprefix_ = None
+        if manonly is None:
+            self.manonly = []
+        else:
+            self.manonly = manonly
+        self.manonly_nsprefix_ = None
+        if xmlonly is None:
+            self.xmlonly = []
+        else:
+            self.xmlonly = xmlonly
+        self.xmlonly_nsprefix_ = None
+        if rtfonly is None:
+            self.rtfonly = []
+        else:
+            self.rtfonly = rtfonly
+        self.rtfonly_nsprefix_ = None
+        if latexonly is None:
+            self.latexonly = []
+        else:
+            self.latexonly = latexonly
+        self.latexonly_nsprefix_ = None
+        if docbookonly is None:
+            self.docbookonly = []
+        else:
+            self.docbookonly = docbookonly
+        self.docbookonly_nsprefix_ = None
+        if image is None:
+            self.image = []
+        else:
+            self.image = image
+        self.image_nsprefix_ = None
+        if dot is None:
+            self.dot = []
+        else:
+            self.dot = dot
+        self.dot_nsprefix_ = None
+        if msc is None:
+            self.msc = []
+        else:
+            self.msc = msc
+        self.msc_nsprefix_ = None
+        if plantuml is None:
+            self.plantuml = []
+        else:
+            self.plantuml = plantuml
+        self.plantuml_nsprefix_ = None
+        if anchor is None:
+            self.anchor = []
+        else:
+            self.anchor = anchor
+        self.anchor_nsprefix_ = None
+        if formula is None:
+            self.formula = []
+        else:
+            self.formula = formula
+        self.formula_nsprefix_ = None
+        if ref is None:
+            self.ref = []
+        else:
+            self.ref = ref
+        self.ref_nsprefix_ = None
+        if emoji is None:
+            self.emoji = []
+        else:
+            self.emoji = emoji
+        self.emoji_nsprefix_ = None
+        if linebreak is None:
+            self.linebreak = []
+        else:
+            self.linebreak = linebreak
+        self.linebreak_nsprefix_ = None
+        self.valueOf_ = valueOf_
+        if mixedclass_ is None:
+            self.mixedclass_ = MixedContainer
+        else:
+            self.mixedclass_ = mixedclass_
+        if content_ is None:
+            self.content_ = []
+        else:
+            self.content_ = content_
+        self.valueOf_ = valueOf_
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(
+                CurrentSubclassModule_, docImageFileType)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if docImageFileType.subclass:
+            return docImageFileType.subclass(*args_, **kwargs_)
+        else:
+            return docImageFileType(*args_, **kwargs_)
+    factory = staticmethod(factory)
+    def get_ns_prefix_(self):
+        return self.ns_prefix_
+    def set_ns_prefix_(self, ns_prefix):
+        self.ns_prefix_ = ns_prefix
+    def get_ulink(self):
+        return self.ulink
+    def set_ulink(self, ulink):
+        self.ulink = ulink
+    def add_ulink(self, value):
+        self.ulink.append(value)
+    def insert_ulink_at(self, index, value):
+        self.ulink.insert(index, value)
+    def replace_ulink_at(self, index, value):
+        self.ulink[index] = value
+    def get_bold(self):
+        return self.bold
+    def set_bold(self, bold):
+        self.bold = bold
+    def add_bold(self, value):
+        self.bold.append(value)
+    def insert_bold_at(self, index, value):
+        self.bold.insert(index, value)
+    def replace_bold_at(self, index, value):
+        self.bold[index] = value
+    def get_s(self):
+        return self.s
+    def set_s(self, s):
+        self.s = s
+    def add_s(self, value):
+        self.s.append(value)
+    def insert_s_at(self, index, value):
+        self.s.insert(index, value)
+    def replace_s_at(self, index, value):
+        self.s[index] = value
+    def get_strike(self):
+        return self.strike
+    def set_strike(self, strike):
+        self.strike = strike
+    def add_strike(self, value):
+        self.strike.append(value)
+    def insert_strike_at(self, index, value):
+        self.strike.insert(index, value)
+    def replace_strike_at(self, index, value):
+        self.strike[index] = value
+    def get_underline(self):
+        return self.underline
+    def set_underline(self, underline):
+        self.underline = underline
+    def add_underline(self, value):
+        self.underline.append(value)
+    def insert_underline_at(self, index, value):
+        self.underline.insert(index, value)
+    def replace_underline_at(self, index, value):
+        self.underline[index] = value
+    def get_emphasis(self):
+        return self.emphasis
+    def set_emphasis(self, emphasis):
+        self.emphasis = emphasis
+    def add_emphasis(self, value):
+        self.emphasis.append(value)
+    def insert_emphasis_at(self, index, value):
+        self.emphasis.insert(index, value)
+    def replace_emphasis_at(self, index, value):
+        self.emphasis[index] = value
+    def get_computeroutput(self):
+        return self.computeroutput
+    def set_computeroutput(self, computeroutput):
+        self.computeroutput = computeroutput
+    def add_computeroutput(self, value):
+        self.computeroutput.append(value)
+    def insert_computeroutput_at(self, index, value):
+        self.computeroutput.insert(index, value)
+    def replace_computeroutput_at(self, index, value):
+        self.computeroutput[index] = value
+    def get_subscript(self):
+        return self.subscript
+    def set_subscript(self, subscript):
+        self.subscript = subscript
+    def add_subscript(self, value):
+        self.subscript.append(value)
+    def insert_subscript_at(self, index, value):
+        self.subscript.insert(index, value)
+    def replace_subscript_at(self, index, value):
+        self.subscript[index] = value
+    def get_superscript(self):
+        return self.superscript
+    def set_superscript(self, superscript):
+        self.superscript = superscript
+    def add_superscript(self, value):
+        self.superscript.append(value)
+    def insert_superscript_at(self, index, value):
+        self.superscript.insert(index, value)
+    def replace_superscript_at(self, index, value):
+        self.superscript[index] = value
+    def get_center(self):
+        return self.center
+    def set_center(self, center):
+        self.center = center
+    def add_center(self, value):
+        self.center.append(value)
+    def insert_center_at(self, index, value):
+        self.center.insert(index, value)
+    def replace_center_at(self, index, value):
+        self.center[index] = value
+    def get_small(self):
+        return self.small
+    def set_small(self, small):
+        self.small = small
+    def add_small(self, value):
+        self.small.append(value)
+    def insert_small_at(self, index, value):
+        self.small.insert(index, value)
+    def replace_small_at(self, index, value):
+        self.small[index] = value
+    def get_cite(self):
+        return self.cite
+    def set_cite(self, cite):
+        self.cite = cite
+    def add_cite(self, value):
+        self.cite.append(value)
+    def insert_cite_at(self, index, value):
+        self.cite.insert(index, value)
+    def replace_cite_at(self, index, value):
+        self.cite[index] = value
+    def get_del(self):
+        return self.del_
+    def set_del(self, del_):
+        self.del_ = del_
+    def add_del(self, value):
+        self.del_.append(value)
+    def insert_del_at(self, index, value):
+        self.del_.insert(index, value)
+    def replace_del_at(self, index, value):
+        self.del_[index] = value
+    def get_ins(self):
+        return self.ins
+    def set_ins(self, ins):
+        self.ins = ins
+    def add_ins(self, value):
+        self.ins.append(value)
+    def insert_ins_at(self, index, value):
+        self.ins.insert(index, value)
+    def replace_ins_at(self, index, value):
+        self.ins[index] = value
+    def get_details(self):
+        return self.details
+    def set_details(self, details):
+        self.details = details
+    def add_details(self, value):
+        self.details.append(value)
+    def insert_details_at(self, index, value):
+        self.details.insert(index, value)
+    def replace_details_at(self, index, value):
+        self.details[index] = value
+    def get_summary(self):
+        return self.summary
+    def set_summary(self, summary):
+        self.summary = summary
+    def add_summary(self, value):
+        self.summary.append(value)
+    def insert_summary_at(self, index, value):
+        self.summary.insert(index, value)
+    def replace_summary_at(self, index, value):
+        self.summary[index] = value
+    def get_htmlonly(self):
+        return self.htmlonly
+    def set_htmlonly(self, htmlonly):
+        self.htmlonly = htmlonly
+    def add_htmlonly(self, value):
+        self.htmlonly.append(value)
+    def insert_htmlonly_at(self, index, value):
+        self.htmlonly.insert(index, value)
+    def replace_htmlonly_at(self, index, value):
+        self.htmlonly[index] = value
+    def get_manonly(self):
+        return self.manonly
+    def set_manonly(self, manonly):
+        self.manonly = manonly
+    def add_manonly(self, value):
+        self.manonly.append(value)
+    def insert_manonly_at(self, index, value):
+        self.manonly.insert(index, value)
+    def replace_manonly_at(self, index, value):
+        self.manonly[index] = value
+    def get_xmlonly(self):
+        return self.xmlonly
+    def set_xmlonly(self, xmlonly):
+        self.xmlonly = xmlonly
+    def add_xmlonly(self, value):
+        self.xmlonly.append(value)
+    def insert_xmlonly_at(self, index, value):
+        self.xmlonly.insert(index, value)
+    def replace_xmlonly_at(self, index, value):
+        self.xmlonly[index] = value
+    def get_rtfonly(self):
+        return self.rtfonly
+    def set_rtfonly(self, rtfonly):
+        self.rtfonly = rtfonly
+    def add_rtfonly(self, value):
+        self.rtfonly.append(value)
+    def insert_rtfonly_at(self, index, value):
+        self.rtfonly.insert(index, value)
+    def replace_rtfonly_at(self, index, value):
+        self.rtfonly[index] = value
+    def get_latexonly(self):
+        return self.latexonly
+    def set_latexonly(self, latexonly):
+        self.latexonly = latexonly
+    def add_latexonly(self, value):
+        self.latexonly.append(value)
+    def insert_latexonly_at(self, index, value):
+        self.latexonly.insert(index, value)
+    def replace_latexonly_at(self, index, value):
+        self.latexonly[index] = value
+    def get_docbookonly(self):
+        return self.docbookonly
+    def set_docbookonly(self, docbookonly):
+        self.docbookonly = docbookonly
+    def add_docbookonly(self, value):
+        self.docbookonly.append(value)
+    def insert_docbookonly_at(self, index, value):
+        self.docbookonly.insert(index, value)
+    def replace_docbookonly_at(self, index, value):
+        self.docbookonly[index] = value
+    def get_image(self):
+        return self.image
+    def set_image(self, image):
+        self.image = image
+    def add_image(self, value):
+        self.image.append(value)
+    def insert_image_at(self, index, value):
+        self.image.insert(index, value)
+    def replace_image_at(self, index, value):
+        self.image[index] = value
+    def get_dot(self):
+        return self.dot
+    def set_dot(self, dot):
+        self.dot = dot
+    def add_dot(self, value):
+        self.dot.append(value)
+    def insert_dot_at(self, index, value):
+        self.dot.insert(index, value)
+    def replace_dot_at(self, index, value):
+        self.dot[index] = value
+    def get_msc(self):
+        return self.msc
+    def set_msc(self, msc):
+        self.msc = msc
+    def add_msc(self, value):
+        self.msc.append(value)
+    def insert_msc_at(self, index, value):
+        self.msc.insert(index, value)
+    def replace_msc_at(self, index, value):
+        self.msc[index] = value
+    def get_plantuml(self):
+        return self.plantuml
+    def set_plantuml(self, plantuml):
+        self.plantuml = plantuml
+    def add_plantuml(self, value):
+        self.plantuml.append(value)
+    def insert_plantuml_at(self, index, value):
+        self.plantuml.insert(index, value)
+    def replace_plantuml_at(self, index, value):
+        self.plantuml[index] = value
+    def get_anchor(self):
+        return self.anchor
+    def set_anchor(self, anchor):
+        self.anchor = anchor
+    def add_anchor(self, value):
+        self.anchor.append(value)
+    def insert_anchor_at(self, index, value):
+        self.anchor.insert(index, value)
+    def replace_anchor_at(self, index, value):
+        self.anchor[index] = value
+    def get_formula(self):
+        return self.formula
+    def set_formula(self, formula):
+        self.formula = formula
+    def add_formula(self, value):
+        self.formula.append(value)
+    def insert_formula_at(self, index, value):
+        self.formula.insert(index, value)
+    def replace_formula_at(self, index, value):
+        self.formula[index] = value
+    def get_ref(self):
+        return self.ref
+    def set_ref(self, ref):
+        self.ref = ref
+    def add_ref(self, value):
+        self.ref.append(value)
+    def insert_ref_at(self, index, value):
+        self.ref.insert(index, value)
+    def replace_ref_at(self, index, value):
+        self.ref[index] = value
+    def get_emoji(self):
+        return self.emoji
+    def set_emoji(self, emoji):
+        self.emoji = emoji
+    def add_emoji(self, value):
+        self.emoji.append(value)
+    def insert_emoji_at(self, index, value):
+        self.emoji.insert(index, value)
+    def replace_emoji_at(self, index, value):
+        self.emoji[index] = value
+    def get_linebreak(self):
+        return self.linebreak
+    def set_linebreak(self, linebreak):
+        self.linebreak = linebreak
+    def add_linebreak(self, value):
+        self.linebreak.append(value)
+    def insert_linebreak_at(self, index, value):
+        self.linebreak.insert(index, value)
+    def replace_linebreak_at(self, index, value):
+        self.linebreak[index] = value
+    def get_name(self):
+        return self.name
+    def set_name(self, name):
+        self.name = name
+    def get_width(self):
+        return self.width
+    def set_width(self, width):
+        self.width = width
+    def get_height(self):
+        return self.height
+    def set_height(self, height):
+        self.height = height
+    def get_valueOf_(self): return self.valueOf_
+    def set_valueOf_(self, valueOf_): self.valueOf_ = valueOf_
+    def hasContent_(self):
+        if (
+            self.ulink or
+            self.bold or
+            self.s or
+            self.strike or
+            self.underline or
+            self.emphasis or
+            self.computeroutput or
+            self.subscript or
+            self.superscript or
+            self.center or
+            self.small or
+            self.cite or
+            self.del_ or
+            self.ins or
+            self.details or
+            self.summary or
+            self.htmlonly or
+            self.manonly or
+            self.xmlonly or
+            self.rtfonly or
+            self.latexonly or
+            self.docbookonly or
+            self.image or
+            self.dot or
+            self.msc or
+            self.plantuml or
+            self.anchor or
+            self.formula or
+            self.ref or
+            self.emoji or
+            self.linebreak or
+            (1 if type(self.valueOf_) in [int,float] else self.valueOf_) or
+            self.content_
+        ):
+            return True
+        else:
+            return False
+    def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='docImageFileType', pretty_print=True):
+        imported_ns_def_ = GenerateDSNamespaceDefs_.get('docImageFileType')
+        if imported_ns_def_ is not None:
+            namespacedef_ = imported_ns_def_
+        if pretty_print:
+            eol_ = '\n'
+        else:
+            eol_ = ''
+        if self.original_tagname_ is not None and name_ == 'docImageFileType':
+            name_ = self.original_tagname_
+        if UseCapturedNS_ and self.ns_prefix_:
+            namespaceprefix_ = self.ns_prefix_ + ':'
+        showIndent(outfile, level, pretty_print)
+        outfile.write('<%s%s%s' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+        already_processed = set()
+        self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='docImageFileType')
+        if self.hasContent_():
+            outfile.write('>%s' % (eol_, ))
+            self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='docImageFileType', pretty_print=pretty_print)
+            showIndent(outfile, level, pretty_print)
+            outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+        else:
+            outfile.write('/>%s' % (eol_, ))
+    def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='docImageFileType'):
+        if self.name is not None and 'name' not in already_processed:
+            already_processed.add('name')
+            outfile.write(' name=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.name), input_name='name')), ))
+        if self.width is not None and 'width' not in already_processed:
+            already_processed.add('width')
+            outfile.write(' width=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.width), input_name='width')), ))
+        if self.height is not None and 'height' not in already_processed:
+            already_processed.add('height')
+            outfile.write(' height=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.height), input_name='height')), ))
+    def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='docImageFileType', fromsubclass_=False, pretty_print=True):
+        if not fromsubclass_:
+            for item_ in self.content_:
+                item_.export(outfile, level, item_.name, namespaceprefix_, pretty_print=pretty_print)
+        if pretty_print:
+            eol_ = '\n'
+        else:
+            eol_ = ''
+        for ulink_ in self.ulink:
+            namespaceprefix_ = self.ulink_nsprefix_ + ':' if (UseCapturedNS_ and self.ulink_nsprefix_) else ''
+            ulink_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ulink', pretty_print=pretty_print)
+        for bold_ in self.bold:
+            namespaceprefix_ = self.bold_nsprefix_ + ':' if (UseCapturedNS_ and self.bold_nsprefix_) else ''
+            bold_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='bold', pretty_print=pretty_print)
+        for s_ in self.s:
+            namespaceprefix_ = self.s_nsprefix_ + ':' if (UseCapturedNS_ and self.s_nsprefix_) else ''
+            s_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='s', pretty_print=pretty_print)
+        for strike_ in self.strike:
+            namespaceprefix_ = self.strike_nsprefix_ + ':' if (UseCapturedNS_ and self.strike_nsprefix_) else ''
+            strike_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='strike', pretty_print=pretty_print)
+        for underline_ in self.underline:
+            namespaceprefix_ = self.underline_nsprefix_ + ':' if (UseCapturedNS_ and self.underline_nsprefix_) else ''
+            underline_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='underline', pretty_print=pretty_print)
+        for emphasis_ in self.emphasis:
+            namespaceprefix_ = self.emphasis_nsprefix_ + ':' if (UseCapturedNS_ and self.emphasis_nsprefix_) else ''
+            emphasis_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='emphasis', pretty_print=pretty_print)
+        for computeroutput_ in self.computeroutput:
+            namespaceprefix_ = self.computeroutput_nsprefix_ + ':' if (UseCapturedNS_ and self.computeroutput_nsprefix_) else ''
+            computeroutput_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='computeroutput', pretty_print=pretty_print)
+        for subscript_ in self.subscript:
+            namespaceprefix_ = self.subscript_nsprefix_ + ':' if (UseCapturedNS_ and self.subscript_nsprefix_) else ''
+            subscript_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='subscript', pretty_print=pretty_print)
+        for superscript_ in self.superscript:
+            namespaceprefix_ = self.superscript_nsprefix_ + ':' if (UseCapturedNS_ and self.superscript_nsprefix_) else ''
+            superscript_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='superscript', pretty_print=pretty_print)
+        for center_ in self.center:
+            namespaceprefix_ = self.center_nsprefix_ + ':' if (UseCapturedNS_ and self.center_nsprefix_) else ''
+            center_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='center', pretty_print=pretty_print)
+        for small_ in self.small:
+            namespaceprefix_ = self.small_nsprefix_ + ':' if (UseCapturedNS_ and self.small_nsprefix_) else ''
+            small_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='small', pretty_print=pretty_print)
+        for cite_ in self.cite:
+            namespaceprefix_ = self.cite_nsprefix_ + ':' if (UseCapturedNS_ and self.cite_nsprefix_) else ''
+            cite_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='cite', pretty_print=pretty_print)
+        for del_ in self.del_:
+            namespaceprefix_ = self.del__nsprefix_ + ':' if (UseCapturedNS_ and self.del__nsprefix_) else ''
+            del_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='del', pretty_print=pretty_print)
+        for ins_ in self.ins:
+            namespaceprefix_ = self.ins_nsprefix_ + ':' if (UseCapturedNS_ and self.ins_nsprefix_) else ''
+            ins_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ins', pretty_print=pretty_print)
+        for details_ in self.details:
+            namespaceprefix_ = self.details_nsprefix_ + ':' if (UseCapturedNS_ and self.details_nsprefix_) else ''
+            details_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='details', pretty_print=pretty_print)
+        for summary_ in self.summary:
+            namespaceprefix_ = self.summary_nsprefix_ + ':' if (UseCapturedNS_ and self.summary_nsprefix_) else ''
+            summary_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='summary', pretty_print=pretty_print)
+        for htmlonly_ in self.htmlonly:
+            namespaceprefix_ = self.htmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.htmlonly_nsprefix_) else ''
+            htmlonly_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='htmlonly', pretty_print=pretty_print)
+        for manonly_ in self.manonly:
+            namespaceprefix_ = self.manonly_nsprefix_ + ':' if (UseCapturedNS_ and self.manonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%smanonly>%s</%smanonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(manonly_), input_name='manonly')), namespaceprefix_ , eol_))
+        for xmlonly_ in self.xmlonly:
+            namespaceprefix_ = self.xmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.xmlonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%sxmlonly>%s</%sxmlonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(xmlonly_), input_name='xmlonly')), namespaceprefix_ , eol_))
+        for rtfonly_ in self.rtfonly:
+            namespaceprefix_ = self.rtfonly_nsprefix_ + ':' if (UseCapturedNS_ and self.rtfonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%srtfonly>%s</%srtfonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(rtfonly_), input_name='rtfonly')), namespaceprefix_ , eol_))
+        for latexonly_ in self.latexonly:
+            namespaceprefix_ = self.latexonly_nsprefix_ + ':' if (UseCapturedNS_ and self.latexonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%slatexonly>%s</%slatexonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(latexonly_), input_name='latexonly')), namespaceprefix_ , eol_))
+        for docbookonly_ in self.docbookonly:
+            namespaceprefix_ = self.docbookonly_nsprefix_ + ':' if (UseCapturedNS_ and self.docbookonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%sdocbookonly>%s</%sdocbookonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(docbookonly_), input_name='docbookonly')), namespaceprefix_ , eol_))
+        for image_ in self.image:
+            namespaceprefix_ = self.image_nsprefix_ + ':' if (UseCapturedNS_ and self.image_nsprefix_) else ''
+            image_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='image', pretty_print=pretty_print)
+        for dot_ in self.dot:
+            namespaceprefix_ = self.dot_nsprefix_ + ':' if (UseCapturedNS_ and self.dot_nsprefix_) else ''
+            dot_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='dot', pretty_print=pretty_print)
+        for msc_ in self.msc:
+            namespaceprefix_ = self.msc_nsprefix_ + ':' if (UseCapturedNS_ and self.msc_nsprefix_) else ''
+            msc_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='msc', pretty_print=pretty_print)
+        for plantuml_ in self.plantuml:
+            namespaceprefix_ = self.plantuml_nsprefix_ + ':' if (UseCapturedNS_ and self.plantuml_nsprefix_) else ''
+            plantuml_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='plantuml', pretty_print=pretty_print)
+        for anchor_ in self.anchor:
+            namespaceprefix_ = self.anchor_nsprefix_ + ':' if (UseCapturedNS_ and self.anchor_nsprefix_) else ''
+            anchor_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='anchor', pretty_print=pretty_print)
+        for formula_ in self.formula:
+            namespaceprefix_ = self.formula_nsprefix_ + ':' if (UseCapturedNS_ and self.formula_nsprefix_) else ''
+            formula_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='formula', pretty_print=pretty_print)
+        for ref_ in self.ref:
+            namespaceprefix_ = self.ref_nsprefix_ + ':' if (UseCapturedNS_ and self.ref_nsprefix_) else ''
+            ref_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ref', pretty_print=pretty_print)
+        for emoji_ in self.emoji:
+            namespaceprefix_ = self.emoji_nsprefix_ + ':' if (UseCapturedNS_ and self.emoji_nsprefix_) else ''
+            emoji_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='emoji', pretty_print=pretty_print)
+        for linebreak_ in self.linebreak:
+            namespaceprefix_ = self.linebreak_nsprefix_ + ':' if (UseCapturedNS_ and self.linebreak_nsprefix_) else ''
+            linebreak_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='linebreak', pretty_print=pretty_print)
+    def build(self, node, gds_collector_=None):
+        self.gds_collector_ = gds_collector_
+        if SaveElementTreeNode:
+            self.gds_elementtree_node_ = node
+        already_processed = set()
+        self.ns_prefix_ = node.prefix
+        self.buildAttributes(node, node.attrib, already_processed)
+        self.valueOf_ = get_all_text_(node)
+        if node.text is not None:
+            obj_ = self.mixedclass_(MixedContainer.CategoryText,
+                MixedContainer.TypeNone, '', node.text)
+            self.content_.append(obj_)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_, gds_collector_=gds_collector_)
+        return self
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_('name', node)
+        if value is not None and 'name' not in already_processed:
+            already_processed.add('name')
+            self.name = value
+        value = find_attr_value_('width', node)
+        if value is not None and 'width' not in already_processed:
+            already_processed.add('width')
+            self.width = value
+        value = find_attr_value_('height', node)
+        if value is not None and 'height' not in already_processed:
+            already_processed.add('height')
+            self.height = value
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False, gds_collector_=None):
+        if nodeName_ == 'ulink':
+            obj_ = docURLLink.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'ulink', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_ulink'):
+              self.add_ulink(obj_.value)
+            elif hasattr(self, 'set_ulink'):
+              self.set_ulink(obj_.value)
+        elif nodeName_ == 'bold':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'bold', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_bold'):
+              self.add_bold(obj_.value)
+            elif hasattr(self, 'set_bold'):
+              self.set_bold(obj_.value)
+        elif nodeName_ == 's':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 's', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_s'):
+              self.add_s(obj_.value)
+            elif hasattr(self, 'set_s'):
+              self.set_s(obj_.value)
+        elif nodeName_ == 'strike':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'strike', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_strike'):
+              self.add_strike(obj_.value)
+            elif hasattr(self, 'set_strike'):
+              self.set_strike(obj_.value)
+        elif nodeName_ == 'underline':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'underline', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_underline'):
+              self.add_underline(obj_.value)
+            elif hasattr(self, 'set_underline'):
+              self.set_underline(obj_.value)
+        elif nodeName_ == 'emphasis':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'emphasis', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_emphasis'):
+              self.add_emphasis(obj_.value)
+            elif hasattr(self, 'set_emphasis'):
+              self.set_emphasis(obj_.value)
+        elif nodeName_ == 'computeroutput':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'computeroutput', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_computeroutput'):
+              self.add_computeroutput(obj_.value)
+            elif hasattr(self, 'set_computeroutput'):
+              self.set_computeroutput(obj_.value)
+        elif nodeName_ == 'subscript':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'subscript', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_subscript'):
+              self.add_subscript(obj_.value)
+            elif hasattr(self, 'set_subscript'):
+              self.set_subscript(obj_.value)
+        elif nodeName_ == 'superscript':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'superscript', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_superscript'):
+              self.add_superscript(obj_.value)
+            elif hasattr(self, 'set_superscript'):
+              self.set_superscript(obj_.value)
+        elif nodeName_ == 'center':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'center', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_center'):
+              self.add_center(obj_.value)
+            elif hasattr(self, 'set_center'):
+              self.set_center(obj_.value)
+        elif nodeName_ == 'small':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'small', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_small'):
+              self.add_small(obj_.value)
+            elif hasattr(self, 'set_small'):
+              self.set_small(obj_.value)
+        elif nodeName_ == 'cite':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'cite', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_cite'):
+              self.add_cite(obj_.value)
+            elif hasattr(self, 'set_cite'):
+              self.set_cite(obj_.value)
+        elif nodeName_ == 'del':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'del', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_del'):
+              self.add_del(obj_.value)
+            elif hasattr(self, 'set_del'):
+              self.set_del(obj_.value)
+        elif nodeName_ == 'ins':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'ins', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_ins'):
+              self.add_ins(obj_.value)
+            elif hasattr(self, 'set_ins'):
+              self.set_ins(obj_.value)
+        elif nodeName_ == 'details':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'details', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_details'):
+              self.add_details(obj_.value)
+            elif hasattr(self, 'set_details'):
+              self.set_details(obj_.value)
+        elif nodeName_ == 'summary':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'summary', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_summary'):
+              self.add_summary(obj_.value)
+            elif hasattr(self, 'set_summary'):
+              self.set_summary(obj_.value)
+        elif nodeName_ == 'htmlonly':
+            obj_ = docHtmlOnlyType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'htmlonly', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_htmlonly'):
+              self.add_htmlonly(obj_.value)
+            elif hasattr(self, 'set_htmlonly'):
+              self.set_htmlonly(obj_.value)
+        elif nodeName_ == 'manonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'manonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'manonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'manonly', valuestr_)
+            self.content_.append(obj_)
+            self.manonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'xmlonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'xmlonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'xmlonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'xmlonly', valuestr_)
+            self.content_.append(obj_)
+            self.xmlonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'rtfonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'rtfonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'rtfonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'rtfonly', valuestr_)
+            self.content_.append(obj_)
+            self.rtfonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'latexonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'latexonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'latexonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'latexonly', valuestr_)
+            self.content_.append(obj_)
+            self.latexonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'docbookonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'docbookonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'docbookonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'docbookonly', valuestr_)
+            self.content_.append(obj_)
+            self.docbookonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'image':
+            obj_ = docImageType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'image', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_image'):
+              self.add_image(obj_.value)
+            elif hasattr(self, 'set_image'):
+              self.set_image(obj_.value)
+        elif nodeName_ == 'dot':
+            obj_ = docDotMscType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'dot', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_dot'):
+              self.add_dot(obj_.value)
+            elif hasattr(self, 'set_dot'):
+              self.set_dot(obj_.value)
+        elif nodeName_ == 'msc':
+            obj_ = docDotMscType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'msc', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_msc'):
+              self.add_msc(obj_.value)
+            elif hasattr(self, 'set_msc'):
+              self.set_msc(obj_.value)
+        elif nodeName_ == 'plantuml':
+            obj_ = docPlantumlType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'plantuml', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_plantuml'):
+              self.add_plantuml(obj_.value)
+            elif hasattr(self, 'set_plantuml'):
+              self.set_plantuml(obj_.value)
+        elif nodeName_ == 'anchor':
+            obj_ = docAnchorType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'anchor', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_anchor'):
+              self.add_anchor(obj_.value)
+            elif hasattr(self, 'set_anchor'):
+              self.set_anchor(obj_.value)
+        elif nodeName_ == 'formula':
+            obj_ = docFormulaType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'formula', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_formula'):
+              self.add_formula(obj_.value)
+            elif hasattr(self, 'set_formula'):
+              self.set_formula(obj_.value)
+        elif nodeName_ == 'ref':
+            obj_ = docRefTextType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'ref', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_ref'):
+              self.add_ref(obj_.value)
+            elif hasattr(self, 'set_ref'):
+              self.set_ref(obj_.value)
+        elif nodeName_ == 'emoji':
+            obj_ = docEmojiType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'emoji', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_emoji'):
+              self.add_emoji(obj_.value)
+            elif hasattr(self, 'set_emoji'):
+              self.set_emoji(obj_.value)
+        elif nodeName_ == 'linebreak':
+            obj_ = docEmptyType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'linebreak', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_linebreak'):
+              self.add_linebreak(obj_.value)
+            elif hasattr(self, 'set_linebreak'):
+              self.set_linebreak(obj_.value)
+        if not fromsubclass_ and child_.tail is not None:
+            obj_ = self.mixedclass_(MixedContainer.CategoryText,
+                MixedContainer.TypeNone, '', child_.tail)
+            self.content_.append(obj_)
+# end class docImageFileType
+
+
+class docPlantumlType(GeneratedsSuper):
+    __hash__ = GeneratedsSuper.__hash__
+    subclass = None
+    superclass = None
+    def __init__(self, name=None, width=None, height=None, caption=None, engine=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, cite=None, del_=None, ins=None, details=None, summary=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
+        self.gds_collector_ = gds_collector_
+        self.gds_elementtree_node_ = None
+        self.original_tagname_ = None
+        self.parent_object_ = kwargs_.get('parent_object_')
+        self.ns_prefix_ = None
+        self.name = _cast(None, name)
+        self.name_nsprefix_ = None
+        self.width = _cast(None, width)
+        self.width_nsprefix_ = None
+        self.height = _cast(None, height)
+        self.height_nsprefix_ = None
+        self.caption = _cast(None, caption)
+        self.caption_nsprefix_ = None
+        self.engine = _cast(None, engine)
+        self.engine_nsprefix_ = None
+        if ulink is None:
+            self.ulink = []
+        else:
+            self.ulink = ulink
+        self.ulink_nsprefix_ = None
+        if bold is None:
+            self.bold = []
+        else:
+            self.bold = bold
+        self.bold_nsprefix_ = None
+        if s is None:
+            self.s = []
+        else:
+            self.s = s
+        self.s_nsprefix_ = None
+        if strike is None:
+            self.strike = []
+        else:
+            self.strike = strike
+        self.strike_nsprefix_ = None
+        if underline is None:
+            self.underline = []
+        else:
+            self.underline = underline
+        self.underline_nsprefix_ = None
+        if emphasis is None:
+            self.emphasis = []
+        else:
+            self.emphasis = emphasis
+        self.emphasis_nsprefix_ = None
+        if computeroutput is None:
+            self.computeroutput = []
+        else:
+            self.computeroutput = computeroutput
+        self.computeroutput_nsprefix_ = None
+        if subscript is None:
+            self.subscript = []
+        else:
+            self.subscript = subscript
+        self.subscript_nsprefix_ = None
+        if superscript is None:
+            self.superscript = []
+        else:
+            self.superscript = superscript
+        self.superscript_nsprefix_ = None
+        if center is None:
+            self.center = []
+        else:
+            self.center = center
+        self.center_nsprefix_ = None
+        if small is None:
+            self.small = []
+        else:
+            self.small = small
+        self.small_nsprefix_ = None
+        if cite is None:
+            self.cite = []
+        else:
+            self.cite = cite
+        self.cite_nsprefix_ = None
+        if del_ is None:
+            self.del_ = []
+        else:
+            self.del_ = del_
+        self.del__nsprefix_ = None
+        if ins is None:
+            self.ins = []
+        else:
+            self.ins = ins
+        self.ins_nsprefix_ = None
+        if details is None:
+            self.details = []
+        else:
+            self.details = details
+        self.details_nsprefix_ = None
+        if summary is None:
+            self.summary = []
+        else:
+            self.summary = summary
+        self.summary_nsprefix_ = None
+        if htmlonly is None:
+            self.htmlonly = []
+        else:
+            self.htmlonly = htmlonly
+        self.htmlonly_nsprefix_ = None
+        if manonly is None:
+            self.manonly = []
+        else:
+            self.manonly = manonly
+        self.manonly_nsprefix_ = None
+        if xmlonly is None:
+            self.xmlonly = []
+        else:
+            self.xmlonly = xmlonly
+        self.xmlonly_nsprefix_ = None
+        if rtfonly is None:
+            self.rtfonly = []
+        else:
+            self.rtfonly = rtfonly
+        self.rtfonly_nsprefix_ = None
+        if latexonly is None:
+            self.latexonly = []
+        else:
+            self.latexonly = latexonly
+        self.latexonly_nsprefix_ = None
+        if docbookonly is None:
+            self.docbookonly = []
+        else:
+            self.docbookonly = docbookonly
+        self.docbookonly_nsprefix_ = None
+        if image is None:
+            self.image = []
+        else:
+            self.image = image
+        self.image_nsprefix_ = None
+        if dot is None:
+            self.dot = []
+        else:
+            self.dot = dot
+        self.dot_nsprefix_ = None
+        if msc is None:
+            self.msc = []
+        else:
+            self.msc = msc
+        self.msc_nsprefix_ = None
+        if plantuml is None:
+            self.plantuml = []
+        else:
+            self.plantuml = plantuml
+        self.plantuml_nsprefix_ = None
+        if anchor is None:
+            self.anchor = []
+        else:
+            self.anchor = anchor
+        self.anchor_nsprefix_ = None
+        if formula is None:
+            self.formula = []
+        else:
+            self.formula = formula
+        self.formula_nsprefix_ = None
+        if ref is None:
+            self.ref = []
+        else:
+            self.ref = ref
+        self.ref_nsprefix_ = None
+        if emoji is None:
+            self.emoji = []
+        else:
+            self.emoji = emoji
+        self.emoji_nsprefix_ = None
+        if linebreak is None:
+            self.linebreak = []
+        else:
+            self.linebreak = linebreak
+        self.linebreak_nsprefix_ = None
+        self.valueOf_ = valueOf_
+        if mixedclass_ is None:
+            self.mixedclass_ = MixedContainer
+        else:
+            self.mixedclass_ = mixedclass_
+        if content_ is None:
+            self.content_ = []
+        else:
+            self.content_ = content_
+        self.valueOf_ = valueOf_
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(
+                CurrentSubclassModule_, docPlantumlType)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if docPlantumlType.subclass:
+            return docPlantumlType.subclass(*args_, **kwargs_)
+        else:
+            return docPlantumlType(*args_, **kwargs_)
+    factory = staticmethod(factory)
+    def get_ns_prefix_(self):
+        return self.ns_prefix_
+    def set_ns_prefix_(self, ns_prefix):
+        self.ns_prefix_ = ns_prefix
+    def get_ulink(self):
+        return self.ulink
+    def set_ulink(self, ulink):
+        self.ulink = ulink
+    def add_ulink(self, value):
+        self.ulink.append(value)
+    def insert_ulink_at(self, index, value):
+        self.ulink.insert(index, value)
+    def replace_ulink_at(self, index, value):
+        self.ulink[index] = value
+    def get_bold(self):
+        return self.bold
+    def set_bold(self, bold):
+        self.bold = bold
+    def add_bold(self, value):
+        self.bold.append(value)
+    def insert_bold_at(self, index, value):
+        self.bold.insert(index, value)
+    def replace_bold_at(self, index, value):
+        self.bold[index] = value
+    def get_s(self):
+        return self.s
+    def set_s(self, s):
+        self.s = s
+    def add_s(self, value):
+        self.s.append(value)
+    def insert_s_at(self, index, value):
+        self.s.insert(index, value)
+    def replace_s_at(self, index, value):
+        self.s[index] = value
+    def get_strike(self):
+        return self.strike
+    def set_strike(self, strike):
+        self.strike = strike
+    def add_strike(self, value):
+        self.strike.append(value)
+    def insert_strike_at(self, index, value):
+        self.strike.insert(index, value)
+    def replace_strike_at(self, index, value):
+        self.strike[index] = value
+    def get_underline(self):
+        return self.underline
+    def set_underline(self, underline):
+        self.underline = underline
+    def add_underline(self, value):
+        self.underline.append(value)
+    def insert_underline_at(self, index, value):
+        self.underline.insert(index, value)
+    def replace_underline_at(self, index, value):
+        self.underline[index] = value
+    def get_emphasis(self):
+        return self.emphasis
+    def set_emphasis(self, emphasis):
+        self.emphasis = emphasis
+    def add_emphasis(self, value):
+        self.emphasis.append(value)
+    def insert_emphasis_at(self, index, value):
+        self.emphasis.insert(index, value)
+    def replace_emphasis_at(self, index, value):
+        self.emphasis[index] = value
+    def get_computeroutput(self):
+        return self.computeroutput
+    def set_computeroutput(self, computeroutput):
+        self.computeroutput = computeroutput
+    def add_computeroutput(self, value):
+        self.computeroutput.append(value)
+    def insert_computeroutput_at(self, index, value):
+        self.computeroutput.insert(index, value)
+    def replace_computeroutput_at(self, index, value):
+        self.computeroutput[index] = value
+    def get_subscript(self):
+        return self.subscript
+    def set_subscript(self, subscript):
+        self.subscript = subscript
+    def add_subscript(self, value):
+        self.subscript.append(value)
+    def insert_subscript_at(self, index, value):
+        self.subscript.insert(index, value)
+    def replace_subscript_at(self, index, value):
+        self.subscript[index] = value
+    def get_superscript(self):
+        return self.superscript
+    def set_superscript(self, superscript):
+        self.superscript = superscript
+    def add_superscript(self, value):
+        self.superscript.append(value)
+    def insert_superscript_at(self, index, value):
+        self.superscript.insert(index, value)
+    def replace_superscript_at(self, index, value):
+        self.superscript[index] = value
+    def get_center(self):
+        return self.center
+    def set_center(self, center):
+        self.center = center
+    def add_center(self, value):
+        self.center.append(value)
+    def insert_center_at(self, index, value):
+        self.center.insert(index, value)
+    def replace_center_at(self, index, value):
+        self.center[index] = value
+    def get_small(self):
+        return self.small
+    def set_small(self, small):
+        self.small = small
+    def add_small(self, value):
+        self.small.append(value)
+    def insert_small_at(self, index, value):
+        self.small.insert(index, value)
+    def replace_small_at(self, index, value):
+        self.small[index] = value
+    def get_cite(self):
+        return self.cite
+    def set_cite(self, cite):
+        self.cite = cite
+    def add_cite(self, value):
+        self.cite.append(value)
+    def insert_cite_at(self, index, value):
+        self.cite.insert(index, value)
+    def replace_cite_at(self, index, value):
+        self.cite[index] = value
+    def get_del(self):
+        return self.del_
+    def set_del(self, del_):
+        self.del_ = del_
+    def add_del(self, value):
+        self.del_.append(value)
+    def insert_del_at(self, index, value):
+        self.del_.insert(index, value)
+    def replace_del_at(self, index, value):
+        self.del_[index] = value
+    def get_ins(self):
+        return self.ins
+    def set_ins(self, ins):
+        self.ins = ins
+    def add_ins(self, value):
+        self.ins.append(value)
+    def insert_ins_at(self, index, value):
+        self.ins.insert(index, value)
+    def replace_ins_at(self, index, value):
+        self.ins[index] = value
+    def get_details(self):
+        return self.details
+    def set_details(self, details):
+        self.details = details
+    def add_details(self, value):
+        self.details.append(value)
+    def insert_details_at(self, index, value):
+        self.details.insert(index, value)
+    def replace_details_at(self, index, value):
+        self.details[index] = value
+    def get_summary(self):
+        return self.summary
+    def set_summary(self, summary):
+        self.summary = summary
+    def add_summary(self, value):
+        self.summary.append(value)
+    def insert_summary_at(self, index, value):
+        self.summary.insert(index, value)
+    def replace_summary_at(self, index, value):
+        self.summary[index] = value
+    def get_htmlonly(self):
+        return self.htmlonly
+    def set_htmlonly(self, htmlonly):
+        self.htmlonly = htmlonly
+    def add_htmlonly(self, value):
+        self.htmlonly.append(value)
+    def insert_htmlonly_at(self, index, value):
+        self.htmlonly.insert(index, value)
+    def replace_htmlonly_at(self, index, value):
+        self.htmlonly[index] = value
+    def get_manonly(self):
+        return self.manonly
+    def set_manonly(self, manonly):
+        self.manonly = manonly
+    def add_manonly(self, value):
+        self.manonly.append(value)
+    def insert_manonly_at(self, index, value):
+        self.manonly.insert(index, value)
+    def replace_manonly_at(self, index, value):
+        self.manonly[index] = value
+    def get_xmlonly(self):
+        return self.xmlonly
+    def set_xmlonly(self, xmlonly):
+        self.xmlonly = xmlonly
+    def add_xmlonly(self, value):
+        self.xmlonly.append(value)
+    def insert_xmlonly_at(self, index, value):
+        self.xmlonly.insert(index, value)
+    def replace_xmlonly_at(self, index, value):
+        self.xmlonly[index] = value
+    def get_rtfonly(self):
+        return self.rtfonly
+    def set_rtfonly(self, rtfonly):
+        self.rtfonly = rtfonly
+    def add_rtfonly(self, value):
+        self.rtfonly.append(value)
+    def insert_rtfonly_at(self, index, value):
+        self.rtfonly.insert(index, value)
+    def replace_rtfonly_at(self, index, value):
+        self.rtfonly[index] = value
+    def get_latexonly(self):
+        return self.latexonly
+    def set_latexonly(self, latexonly):
+        self.latexonly = latexonly
+    def add_latexonly(self, value):
+        self.latexonly.append(value)
+    def insert_latexonly_at(self, index, value):
+        self.latexonly.insert(index, value)
+    def replace_latexonly_at(self, index, value):
+        self.latexonly[index] = value
+    def get_docbookonly(self):
+        return self.docbookonly
+    def set_docbookonly(self, docbookonly):
+        self.docbookonly = docbookonly
+    def add_docbookonly(self, value):
+        self.docbookonly.append(value)
+    def insert_docbookonly_at(self, index, value):
+        self.docbookonly.insert(index, value)
+    def replace_docbookonly_at(self, index, value):
+        self.docbookonly[index] = value
+    def get_image(self):
+        return self.image
+    def set_image(self, image):
+        self.image = image
+    def add_image(self, value):
+        self.image.append(value)
+    def insert_image_at(self, index, value):
+        self.image.insert(index, value)
+    def replace_image_at(self, index, value):
+        self.image[index] = value
+    def get_dot(self):
+        return self.dot
+    def set_dot(self, dot):
+        self.dot = dot
+    def add_dot(self, value):
+        self.dot.append(value)
+    def insert_dot_at(self, index, value):
+        self.dot.insert(index, value)
+    def replace_dot_at(self, index, value):
+        self.dot[index] = value
+    def get_msc(self):
+        return self.msc
+    def set_msc(self, msc):
+        self.msc = msc
+    def add_msc(self, value):
+        self.msc.append(value)
+    def insert_msc_at(self, index, value):
+        self.msc.insert(index, value)
+    def replace_msc_at(self, index, value):
+        self.msc[index] = value
+    def get_plantuml(self):
+        return self.plantuml
+    def set_plantuml(self, plantuml):
+        self.plantuml = plantuml
+    def add_plantuml(self, value):
+        self.plantuml.append(value)
+    def insert_plantuml_at(self, index, value):
+        self.plantuml.insert(index, value)
+    def replace_plantuml_at(self, index, value):
+        self.plantuml[index] = value
+    def get_anchor(self):
+        return self.anchor
+    def set_anchor(self, anchor):
+        self.anchor = anchor
+    def add_anchor(self, value):
+        self.anchor.append(value)
+    def insert_anchor_at(self, index, value):
+        self.anchor.insert(index, value)
+    def replace_anchor_at(self, index, value):
+        self.anchor[index] = value
+    def get_formula(self):
+        return self.formula
+    def set_formula(self, formula):
+        self.formula = formula
+    def add_formula(self, value):
+        self.formula.append(value)
+    def insert_formula_at(self, index, value):
+        self.formula.insert(index, value)
+    def replace_formula_at(self, index, value):
+        self.formula[index] = value
+    def get_ref(self):
+        return self.ref
+    def set_ref(self, ref):
+        self.ref = ref
+    def add_ref(self, value):
+        self.ref.append(value)
+    def insert_ref_at(self, index, value):
+        self.ref.insert(index, value)
+    def replace_ref_at(self, index, value):
+        self.ref[index] = value
+    def get_emoji(self):
+        return self.emoji
+    def set_emoji(self, emoji):
+        self.emoji = emoji
+    def add_emoji(self, value):
+        self.emoji.append(value)
+    def insert_emoji_at(self, index, value):
+        self.emoji.insert(index, value)
+    def replace_emoji_at(self, index, value):
+        self.emoji[index] = value
+    def get_linebreak(self):
+        return self.linebreak
+    def set_linebreak(self, linebreak):
+        self.linebreak = linebreak
+    def add_linebreak(self, value):
+        self.linebreak.append(value)
+    def insert_linebreak_at(self, index, value):
+        self.linebreak.insert(index, value)
+    def replace_linebreak_at(self, index, value):
+        self.linebreak[index] = value
+    def get_name(self):
+        return self.name
+    def set_name(self, name):
+        self.name = name
+    def get_width(self):
+        return self.width
+    def set_width(self, width):
+        self.width = width
+    def get_height(self):
+        return self.height
+    def set_height(self, height):
+        self.height = height
+    def get_caption(self):
+        return self.caption
+    def set_caption(self, caption):
+        self.caption = caption
+    def get_engine(self):
+        return self.engine
+    def set_engine(self, engine):
+        self.engine = engine
+    def get_valueOf_(self): return self.valueOf_
+    def set_valueOf_(self, valueOf_): self.valueOf_ = valueOf_
+    def validate_DoxPlantumlEngine(self, value):
+        # Validate type DoxPlantumlEngine, a restriction on xsd:string.
+        if value is not None and Validate_simpletypes_ and self.gds_collector_ is not None:
+            if not isinstance(value, str):
+                lineno = self.gds_get_node_lineno_()
+                self.gds_collector_.add_message('Value "%(value)s"%(lineno)s is not of the correct base simple type (str)' % {"value": value, "lineno": lineno, })
+                return False
+            value = value
+            enumerations = ['uml', 'bpm', 'wire', 'dot', 'ditaa', 'salt', 'math', 'latex', 'gantt', 'mindmap', 'wbs', 'yaml', 'creole', 'json', 'flow', 'board', 'git']
+            if value not in enumerations:
+                lineno = self.gds_get_node_lineno_()
+                self.gds_collector_.add_message('Value "%(value)s"%(lineno)s does not match xsd enumeration restriction on DoxPlantumlEngine' % {"value" : encode_str_2_3(value), "lineno": lineno} )
+                result = False
+    def hasContent_(self):
+        if (
+            self.ulink or
+            self.bold or
+            self.s or
+            self.strike or
+            self.underline or
+            self.emphasis or
+            self.computeroutput or
+            self.subscript or
+            self.superscript or
+            self.center or
+            self.small or
+            self.cite or
+            self.del_ or
+            self.ins or
+            self.details or
+            self.summary or
+            self.htmlonly or
+            self.manonly or
+            self.xmlonly or
+            self.rtfonly or
+            self.latexonly or
+            self.docbookonly or
+            self.image or
+            self.dot or
+            self.msc or
+            self.plantuml or
+            self.anchor or
+            self.formula or
+            self.ref or
+            self.emoji or
+            self.linebreak or
+            (1 if type(self.valueOf_) in [int,float] else self.valueOf_) or
+            self.content_
+        ):
+            return True
+        else:
+            return False
+    def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='docPlantumlType', pretty_print=True):
+        imported_ns_def_ = GenerateDSNamespaceDefs_.get('docPlantumlType')
+        if imported_ns_def_ is not None:
+            namespacedef_ = imported_ns_def_
+        if pretty_print:
+            eol_ = '\n'
+        else:
+            eol_ = ''
+        if self.original_tagname_ is not None and name_ == 'docPlantumlType':
+            name_ = self.original_tagname_
+        if UseCapturedNS_ and self.ns_prefix_:
+            namespaceprefix_ = self.ns_prefix_ + ':'
+        showIndent(outfile, level, pretty_print)
+        outfile.write('<%s%s%s' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+        already_processed = set()
+        self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='docPlantumlType')
+        if self.hasContent_():
+            outfile.write('>%s' % (eol_, ))
+            self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='docPlantumlType', pretty_print=pretty_print)
+            showIndent(outfile, level, pretty_print)
+            outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+        else:
+            outfile.write('/>%s' % (eol_, ))
+    def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='docPlantumlType'):
+        if self.name is not None and 'name' not in already_processed:
+            already_processed.add('name')
+            outfile.write(' name=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.name), input_name='name')), ))
+        if self.width is not None and 'width' not in already_processed:
+            already_processed.add('width')
+            outfile.write(' width=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.width), input_name='width')), ))
+        if self.height is not None and 'height' not in already_processed:
+            already_processed.add('height')
+            outfile.write(' height=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.height), input_name='height')), ))
+        if self.caption is not None and 'caption' not in already_processed:
+            already_processed.add('caption')
+            outfile.write(' caption=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.caption), input_name='caption')), ))
+        if self.engine is not None and 'engine' not in already_processed:
+            already_processed.add('engine')
+            outfile.write(' engine=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.engine), input_name='engine')), ))
+    def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='docPlantumlType', fromsubclass_=False, pretty_print=True):
+        if not fromsubclass_:
+            for item_ in self.content_:
+                item_.export(outfile, level, item_.name, namespaceprefix_, pretty_print=pretty_print)
+        if pretty_print:
+            eol_ = '\n'
+        else:
+            eol_ = ''
+        for ulink_ in self.ulink:
+            namespaceprefix_ = self.ulink_nsprefix_ + ':' if (UseCapturedNS_ and self.ulink_nsprefix_) else ''
+            ulink_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ulink', pretty_print=pretty_print)
+        for bold_ in self.bold:
+            namespaceprefix_ = self.bold_nsprefix_ + ':' if (UseCapturedNS_ and self.bold_nsprefix_) else ''
+            bold_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='bold', pretty_print=pretty_print)
+        for s_ in self.s:
+            namespaceprefix_ = self.s_nsprefix_ + ':' if (UseCapturedNS_ and self.s_nsprefix_) else ''
+            s_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='s', pretty_print=pretty_print)
+        for strike_ in self.strike:
+            namespaceprefix_ = self.strike_nsprefix_ + ':' if (UseCapturedNS_ and self.strike_nsprefix_) else ''
+            strike_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='strike', pretty_print=pretty_print)
+        for underline_ in self.underline:
+            namespaceprefix_ = self.underline_nsprefix_ + ':' if (UseCapturedNS_ and self.underline_nsprefix_) else ''
+            underline_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='underline', pretty_print=pretty_print)
+        for emphasis_ in self.emphasis:
+            namespaceprefix_ = self.emphasis_nsprefix_ + ':' if (UseCapturedNS_ and self.emphasis_nsprefix_) else ''
+            emphasis_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='emphasis', pretty_print=pretty_print)
+        for computeroutput_ in self.computeroutput:
+            namespaceprefix_ = self.computeroutput_nsprefix_ + ':' if (UseCapturedNS_ and self.computeroutput_nsprefix_) else ''
+            computeroutput_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='computeroutput', pretty_print=pretty_print)
+        for subscript_ in self.subscript:
+            namespaceprefix_ = self.subscript_nsprefix_ + ':' if (UseCapturedNS_ and self.subscript_nsprefix_) else ''
+            subscript_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='subscript', pretty_print=pretty_print)
+        for superscript_ in self.superscript:
+            namespaceprefix_ = self.superscript_nsprefix_ + ':' if (UseCapturedNS_ and self.superscript_nsprefix_) else ''
+            superscript_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='superscript', pretty_print=pretty_print)
+        for center_ in self.center:
+            namespaceprefix_ = self.center_nsprefix_ + ':' if (UseCapturedNS_ and self.center_nsprefix_) else ''
+            center_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='center', pretty_print=pretty_print)
+        for small_ in self.small:
+            namespaceprefix_ = self.small_nsprefix_ + ':' if (UseCapturedNS_ and self.small_nsprefix_) else ''
+            small_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='small', pretty_print=pretty_print)
+        for cite_ in self.cite:
+            namespaceprefix_ = self.cite_nsprefix_ + ':' if (UseCapturedNS_ and self.cite_nsprefix_) else ''
+            cite_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='cite', pretty_print=pretty_print)
+        for del_ in self.del_:
+            namespaceprefix_ = self.del__nsprefix_ + ':' if (UseCapturedNS_ and self.del__nsprefix_) else ''
+            del_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='del', pretty_print=pretty_print)
+        for ins_ in self.ins:
+            namespaceprefix_ = self.ins_nsprefix_ + ':' if (UseCapturedNS_ and self.ins_nsprefix_) else ''
+            ins_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ins', pretty_print=pretty_print)
+        for details_ in self.details:
+            namespaceprefix_ = self.details_nsprefix_ + ':' if (UseCapturedNS_ and self.details_nsprefix_) else ''
+            details_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='details', pretty_print=pretty_print)
+        for summary_ in self.summary:
+            namespaceprefix_ = self.summary_nsprefix_ + ':' if (UseCapturedNS_ and self.summary_nsprefix_) else ''
+            summary_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='summary', pretty_print=pretty_print)
+        for htmlonly_ in self.htmlonly:
+            namespaceprefix_ = self.htmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.htmlonly_nsprefix_) else ''
+            htmlonly_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='htmlonly', pretty_print=pretty_print)
+        for manonly_ in self.manonly:
+            namespaceprefix_ = self.manonly_nsprefix_ + ':' if (UseCapturedNS_ and self.manonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%smanonly>%s</%smanonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(manonly_), input_name='manonly')), namespaceprefix_ , eol_))
+        for xmlonly_ in self.xmlonly:
+            namespaceprefix_ = self.xmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.xmlonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%sxmlonly>%s</%sxmlonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(xmlonly_), input_name='xmlonly')), namespaceprefix_ , eol_))
+        for rtfonly_ in self.rtfonly:
+            namespaceprefix_ = self.rtfonly_nsprefix_ + ':' if (UseCapturedNS_ and self.rtfonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%srtfonly>%s</%srtfonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(rtfonly_), input_name='rtfonly')), namespaceprefix_ , eol_))
+        for latexonly_ in self.latexonly:
+            namespaceprefix_ = self.latexonly_nsprefix_ + ':' if (UseCapturedNS_ and self.latexonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%slatexonly>%s</%slatexonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(latexonly_), input_name='latexonly')), namespaceprefix_ , eol_))
+        for docbookonly_ in self.docbookonly:
+            namespaceprefix_ = self.docbookonly_nsprefix_ + ':' if (UseCapturedNS_ and self.docbookonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%sdocbookonly>%s</%sdocbookonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(docbookonly_), input_name='docbookonly')), namespaceprefix_ , eol_))
+        for image_ in self.image:
+            namespaceprefix_ = self.image_nsprefix_ + ':' if (UseCapturedNS_ and self.image_nsprefix_) else ''
+            image_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='image', pretty_print=pretty_print)
+        for dot_ in self.dot:
+            namespaceprefix_ = self.dot_nsprefix_ + ':' if (UseCapturedNS_ and self.dot_nsprefix_) else ''
+            dot_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='dot', pretty_print=pretty_print)
+        for msc_ in self.msc:
+            namespaceprefix_ = self.msc_nsprefix_ + ':' if (UseCapturedNS_ and self.msc_nsprefix_) else ''
+            msc_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='msc', pretty_print=pretty_print)
+        for plantuml_ in self.plantuml:
+            namespaceprefix_ = self.plantuml_nsprefix_ + ':' if (UseCapturedNS_ and self.plantuml_nsprefix_) else ''
+            plantuml_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='plantuml', pretty_print=pretty_print)
+        for anchor_ in self.anchor:
+            namespaceprefix_ = self.anchor_nsprefix_ + ':' if (UseCapturedNS_ and self.anchor_nsprefix_) else ''
+            anchor_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='anchor', pretty_print=pretty_print)
+        for formula_ in self.formula:
+            namespaceprefix_ = self.formula_nsprefix_ + ':' if (UseCapturedNS_ and self.formula_nsprefix_) else ''
+            formula_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='formula', pretty_print=pretty_print)
+        for ref_ in self.ref:
+            namespaceprefix_ = self.ref_nsprefix_ + ':' if (UseCapturedNS_ and self.ref_nsprefix_) else ''
+            ref_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ref', pretty_print=pretty_print)
+        for emoji_ in self.emoji:
+            namespaceprefix_ = self.emoji_nsprefix_ + ':' if (UseCapturedNS_ and self.emoji_nsprefix_) else ''
+            emoji_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='emoji', pretty_print=pretty_print)
+        for linebreak_ in self.linebreak:
+            namespaceprefix_ = self.linebreak_nsprefix_ + ':' if (UseCapturedNS_ and self.linebreak_nsprefix_) else ''
+            linebreak_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='linebreak', pretty_print=pretty_print)
+    def build(self, node, gds_collector_=None):
+        self.gds_collector_ = gds_collector_
+        if SaveElementTreeNode:
+            self.gds_elementtree_node_ = node
+        already_processed = set()
+        self.ns_prefix_ = node.prefix
+        self.buildAttributes(node, node.attrib, already_processed)
+        self.valueOf_ = get_all_text_(node)
+        if node.text is not None:
+            obj_ = self.mixedclass_(MixedContainer.CategoryText,
+                MixedContainer.TypeNone, '', node.text)
+            self.content_.append(obj_)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_, gds_collector_=gds_collector_)
+        return self
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_('name', node)
+        if value is not None and 'name' not in already_processed:
+            already_processed.add('name')
+            self.name = value
+        value = find_attr_value_('width', node)
+        if value is not None and 'width' not in already_processed:
+            already_processed.add('width')
+            self.width = value
+        value = find_attr_value_('height', node)
+        if value is not None and 'height' not in already_processed:
+            already_processed.add('height')
+            self.height = value
+        value = find_attr_value_('caption', node)
+        if value is not None and 'caption' not in already_processed:
+            already_processed.add('caption')
+            self.caption = value
+        value = find_attr_value_('engine', node)
+        if value is not None and 'engine' not in already_processed:
+            already_processed.add('engine')
+            self.engine = value
+            self.validate_DoxPlantumlEngine(self.engine)    # validate type DoxPlantumlEngine
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False, gds_collector_=None):
+        if nodeName_ == 'ulink':
+            obj_ = docURLLink.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'ulink', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_ulink'):
+              self.add_ulink(obj_.value)
+            elif hasattr(self, 'set_ulink'):
+              self.set_ulink(obj_.value)
+        elif nodeName_ == 'bold':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'bold', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_bold'):
+              self.add_bold(obj_.value)
+            elif hasattr(self, 'set_bold'):
+              self.set_bold(obj_.value)
+        elif nodeName_ == 's':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 's', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_s'):
+              self.add_s(obj_.value)
+            elif hasattr(self, 'set_s'):
+              self.set_s(obj_.value)
+        elif nodeName_ == 'strike':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'strike', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_strike'):
+              self.add_strike(obj_.value)
+            elif hasattr(self, 'set_strike'):
+              self.set_strike(obj_.value)
+        elif nodeName_ == 'underline':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'underline', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_underline'):
+              self.add_underline(obj_.value)
+            elif hasattr(self, 'set_underline'):
+              self.set_underline(obj_.value)
+        elif nodeName_ == 'emphasis':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'emphasis', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_emphasis'):
+              self.add_emphasis(obj_.value)
+            elif hasattr(self, 'set_emphasis'):
+              self.set_emphasis(obj_.value)
+        elif nodeName_ == 'computeroutput':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'computeroutput', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_computeroutput'):
+              self.add_computeroutput(obj_.value)
+            elif hasattr(self, 'set_computeroutput'):
+              self.set_computeroutput(obj_.value)
+        elif nodeName_ == 'subscript':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'subscript', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_subscript'):
+              self.add_subscript(obj_.value)
+            elif hasattr(self, 'set_subscript'):
+              self.set_subscript(obj_.value)
+        elif nodeName_ == 'superscript':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'superscript', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_superscript'):
+              self.add_superscript(obj_.value)
+            elif hasattr(self, 'set_superscript'):
+              self.set_superscript(obj_.value)
+        elif nodeName_ == 'center':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'center', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_center'):
+              self.add_center(obj_.value)
+            elif hasattr(self, 'set_center'):
+              self.set_center(obj_.value)
+        elif nodeName_ == 'small':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'small', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_small'):
+              self.add_small(obj_.value)
+            elif hasattr(self, 'set_small'):
+              self.set_small(obj_.value)
+        elif nodeName_ == 'cite':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'cite', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_cite'):
+              self.add_cite(obj_.value)
+            elif hasattr(self, 'set_cite'):
+              self.set_cite(obj_.value)
+        elif nodeName_ == 'del':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'del', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_del'):
+              self.add_del(obj_.value)
+            elif hasattr(self, 'set_del'):
+              self.set_del(obj_.value)
+        elif nodeName_ == 'ins':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'ins', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_ins'):
+              self.add_ins(obj_.value)
+            elif hasattr(self, 'set_ins'):
+              self.set_ins(obj_.value)
+        elif nodeName_ == 'details':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'details', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_details'):
+              self.add_details(obj_.value)
+            elif hasattr(self, 'set_details'):
+              self.set_details(obj_.value)
+        elif nodeName_ == 'summary':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'summary', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_summary'):
+              self.add_summary(obj_.value)
+            elif hasattr(self, 'set_summary'):
+              self.set_summary(obj_.value)
+        elif nodeName_ == 'htmlonly':
+            obj_ = docHtmlOnlyType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'htmlonly', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_htmlonly'):
+              self.add_htmlonly(obj_.value)
+            elif hasattr(self, 'set_htmlonly'):
+              self.set_htmlonly(obj_.value)
+        elif nodeName_ == 'manonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'manonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'manonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'manonly', valuestr_)
+            self.content_.append(obj_)
+            self.manonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'xmlonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'xmlonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'xmlonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'xmlonly', valuestr_)
+            self.content_.append(obj_)
+            self.xmlonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'rtfonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'rtfonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'rtfonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'rtfonly', valuestr_)
+            self.content_.append(obj_)
+            self.rtfonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'latexonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'latexonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'latexonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'latexonly', valuestr_)
+            self.content_.append(obj_)
+            self.latexonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'docbookonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'docbookonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'docbookonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'docbookonly', valuestr_)
+            self.content_.append(obj_)
+            self.docbookonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'image':
+            obj_ = docImageType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'image', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_image'):
+              self.add_image(obj_.value)
+            elif hasattr(self, 'set_image'):
+              self.set_image(obj_.value)
+        elif nodeName_ == 'dot':
+            obj_ = docDotMscType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'dot', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_dot'):
+              self.add_dot(obj_.value)
+            elif hasattr(self, 'set_dot'):
+              self.set_dot(obj_.value)
+        elif nodeName_ == 'msc':
+            obj_ = docDotMscType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'msc', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_msc'):
+              self.add_msc(obj_.value)
+            elif hasattr(self, 'set_msc'):
+              self.set_msc(obj_.value)
+        elif nodeName_ == 'plantuml':
+            obj_ = docPlantumlType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'plantuml', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_plantuml'):
+              self.add_plantuml(obj_.value)
+            elif hasattr(self, 'set_plantuml'):
+              self.set_plantuml(obj_.value)
+        elif nodeName_ == 'anchor':
+            obj_ = docAnchorType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'anchor', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_anchor'):
+              self.add_anchor(obj_.value)
+            elif hasattr(self, 'set_anchor'):
+              self.set_anchor(obj_.value)
+        elif nodeName_ == 'formula':
+            obj_ = docFormulaType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'formula', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_formula'):
+              self.add_formula(obj_.value)
+            elif hasattr(self, 'set_formula'):
+              self.set_formula(obj_.value)
+        elif nodeName_ == 'ref':
+            obj_ = docRefTextType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'ref', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_ref'):
+              self.add_ref(obj_.value)
+            elif hasattr(self, 'set_ref'):
+              self.set_ref(obj_.value)
+        elif nodeName_ == 'emoji':
+            obj_ = docEmojiType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'emoji', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_emoji'):
+              self.add_emoji(obj_.value)
+            elif hasattr(self, 'set_emoji'):
+              self.set_emoji(obj_.value)
+        elif nodeName_ == 'linebreak':
+            obj_ = docEmptyType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'linebreak', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_linebreak'):
+              self.add_linebreak(obj_.value)
+            elif hasattr(self, 'set_linebreak'):
+              self.set_linebreak(obj_.value)
+        if not fromsubclass_ and child_.tail is not None:
+            obj_ = self.mixedclass_(MixedContainer.CategoryText,
+                MixedContainer.TypeNone, '', child_.tail)
+            self.content_.append(obj_)
+# end class docPlantumlType
+
+
+class docTocItemType(GeneratedsSuper):
+    __hash__ = GeneratedsSuper.__hash__
+    subclass = None
+    superclass = None
+    def __init__(self, id=None, ulink=None, bold=None, s=None, strike=None, underline=None, emphasis=None, computeroutput=None, subscript=None, superscript=None, center=None, small=None, cite=None, del_=None, ins=None, details=None, summary=None, htmlonly=None, manonly=None, xmlonly=None, rtfonly=None, latexonly=None, docbookonly=None, image=None, dot=None, msc=None, plantuml=None, anchor=None, formula=None, ref=None, emoji=None, linebreak=None, valueOf_=None, mixedclass_=None, content_=None, gds_collector_=None, **kwargs_):
+        self.gds_collector_ = gds_collector_
+        self.gds_elementtree_node_ = None
+        self.original_tagname_ = None
+        self.parent_object_ = kwargs_.get('parent_object_')
+        self.ns_prefix_ = None
+        self.id = _cast(None, id)
+        self.id_nsprefix_ = None
+        if ulink is None:
+            self.ulink = []
+        else:
+            self.ulink = ulink
+        self.ulink_nsprefix_ = None
+        if bold is None:
+            self.bold = []
+        else:
+            self.bold = bold
+        self.bold_nsprefix_ = None
+        if s is None:
+            self.s = []
+        else:
+            self.s = s
+        self.s_nsprefix_ = None
+        if strike is None:
+            self.strike = []
+        else:
+            self.strike = strike
+        self.strike_nsprefix_ = None
+        if underline is None:
+            self.underline = []
+        else:
+            self.underline = underline
+        self.underline_nsprefix_ = None
+        if emphasis is None:
+            self.emphasis = []
+        else:
+            self.emphasis = emphasis
+        self.emphasis_nsprefix_ = None
+        if computeroutput is None:
+            self.computeroutput = []
+        else:
+            self.computeroutput = computeroutput
+        self.computeroutput_nsprefix_ = None
+        if subscript is None:
+            self.subscript = []
+        else:
+            self.subscript = subscript
+        self.subscript_nsprefix_ = None
+        if superscript is None:
+            self.superscript = []
+        else:
+            self.superscript = superscript
+        self.superscript_nsprefix_ = None
+        if center is None:
+            self.center = []
+        else:
+            self.center = center
+        self.center_nsprefix_ = None
+        if small is None:
+            self.small = []
+        else:
+            self.small = small
+        self.small_nsprefix_ = None
+        if cite is None:
+            self.cite = []
+        else:
+            self.cite = cite
+        self.cite_nsprefix_ = None
+        if del_ is None:
+            self.del_ = []
+        else:
+            self.del_ = del_
+        self.del__nsprefix_ = None
+        if ins is None:
+            self.ins = []
+        else:
+            self.ins = ins
+        self.ins_nsprefix_ = None
+        if details is None:
+            self.details = []
+        else:
+            self.details = details
+        self.details_nsprefix_ = None
+        if summary is None:
+            self.summary = []
+        else:
+            self.summary = summary
+        self.summary_nsprefix_ = None
+        if htmlonly is None:
+            self.htmlonly = []
+        else:
+            self.htmlonly = htmlonly
+        self.htmlonly_nsprefix_ = None
+        if manonly is None:
+            self.manonly = []
+        else:
+            self.manonly = manonly
+        self.manonly_nsprefix_ = None
+        if xmlonly is None:
+            self.xmlonly = []
+        else:
+            self.xmlonly = xmlonly
+        self.xmlonly_nsprefix_ = None
+        if rtfonly is None:
+            self.rtfonly = []
+        else:
+            self.rtfonly = rtfonly
+        self.rtfonly_nsprefix_ = None
+        if latexonly is None:
+            self.latexonly = []
+        else:
+            self.latexonly = latexonly
+        self.latexonly_nsprefix_ = None
+        if docbookonly is None:
+            self.docbookonly = []
+        else:
+            self.docbookonly = docbookonly
+        self.docbookonly_nsprefix_ = None
+        if image is None:
+            self.image = []
+        else:
+            self.image = image
+        self.image_nsprefix_ = None
+        if dot is None:
+            self.dot = []
+        else:
+            self.dot = dot
+        self.dot_nsprefix_ = None
+        if msc is None:
+            self.msc = []
+        else:
+            self.msc = msc
+        self.msc_nsprefix_ = None
+        if plantuml is None:
+            self.plantuml = []
+        else:
+            self.plantuml = plantuml
+        self.plantuml_nsprefix_ = None
+        if anchor is None:
+            self.anchor = []
+        else:
+            self.anchor = anchor
+        self.anchor_nsprefix_ = None
+        if formula is None:
+            self.formula = []
+        else:
+            self.formula = formula
+        self.formula_nsprefix_ = None
+        if ref is None:
+            self.ref = []
+        else:
+            self.ref = ref
+        self.ref_nsprefix_ = None
+        if emoji is None:
+            self.emoji = []
+        else:
+            self.emoji = emoji
+        self.emoji_nsprefix_ = None
+        if linebreak is None:
+            self.linebreak = []
+        else:
+            self.linebreak = linebreak
+        self.linebreak_nsprefix_ = None
+        self.valueOf_ = valueOf_
+        if mixedclass_ is None:
+            self.mixedclass_ = MixedContainer
+        else:
+            self.mixedclass_ = mixedclass_
+        if content_ is None:
+            self.content_ = []
+        else:
+            self.content_ = content_
+        self.valueOf_ = valueOf_
+    def factory(*args_, **kwargs_):
+        if CurrentSubclassModule_ is not None:
+            subclass = getSubclassFromModule_(
+                CurrentSubclassModule_, docTocItemType)
+            if subclass is not None:
+                return subclass(*args_, **kwargs_)
+        if docTocItemType.subclass:
+            return docTocItemType.subclass(*args_, **kwargs_)
+        else:
+            return docTocItemType(*args_, **kwargs_)
+    factory = staticmethod(factory)
+    def get_ns_prefix_(self):
+        return self.ns_prefix_
+    def set_ns_prefix_(self, ns_prefix):
+        self.ns_prefix_ = ns_prefix
+    def get_ulink(self):
+        return self.ulink
+    def set_ulink(self, ulink):
+        self.ulink = ulink
+    def add_ulink(self, value):
+        self.ulink.append(value)
+    def insert_ulink_at(self, index, value):
+        self.ulink.insert(index, value)
+    def replace_ulink_at(self, index, value):
+        self.ulink[index] = value
+    def get_bold(self):
+        return self.bold
+    def set_bold(self, bold):
+        self.bold = bold
+    def add_bold(self, value):
+        self.bold.append(value)
+    def insert_bold_at(self, index, value):
+        self.bold.insert(index, value)
+    def replace_bold_at(self, index, value):
+        self.bold[index] = value
+    def get_s(self):
+        return self.s
+    def set_s(self, s):
+        self.s = s
+    def add_s(self, value):
+        self.s.append(value)
+    def insert_s_at(self, index, value):
+        self.s.insert(index, value)
+    def replace_s_at(self, index, value):
+        self.s[index] = value
+    def get_strike(self):
+        return self.strike
+    def set_strike(self, strike):
+        self.strike = strike
+    def add_strike(self, value):
+        self.strike.append(value)
+    def insert_strike_at(self, index, value):
+        self.strike.insert(index, value)
+    def replace_strike_at(self, index, value):
+        self.strike[index] = value
+    def get_underline(self):
+        return self.underline
+    def set_underline(self, underline):
+        self.underline = underline
+    def add_underline(self, value):
+        self.underline.append(value)
+    def insert_underline_at(self, index, value):
+        self.underline.insert(index, value)
+    def replace_underline_at(self, index, value):
+        self.underline[index] = value
+    def get_emphasis(self):
+        return self.emphasis
+    def set_emphasis(self, emphasis):
+        self.emphasis = emphasis
+    def add_emphasis(self, value):
+        self.emphasis.append(value)
+    def insert_emphasis_at(self, index, value):
+        self.emphasis.insert(index, value)
+    def replace_emphasis_at(self, index, value):
+        self.emphasis[index] = value
+    def get_computeroutput(self):
+        return self.computeroutput
+    def set_computeroutput(self, computeroutput):
+        self.computeroutput = computeroutput
+    def add_computeroutput(self, value):
+        self.computeroutput.append(value)
+    def insert_computeroutput_at(self, index, value):
+        self.computeroutput.insert(index, value)
+    def replace_computeroutput_at(self, index, value):
+        self.computeroutput[index] = value
+    def get_subscript(self):
+        return self.subscript
+    def set_subscript(self, subscript):
+        self.subscript = subscript
+    def add_subscript(self, value):
+        self.subscript.append(value)
+    def insert_subscript_at(self, index, value):
+        self.subscript.insert(index, value)
+    def replace_subscript_at(self, index, value):
+        self.subscript[index] = value
+    def get_superscript(self):
+        return self.superscript
+    def set_superscript(self, superscript):
+        self.superscript = superscript
+    def add_superscript(self, value):
+        self.superscript.append(value)
+    def insert_superscript_at(self, index, value):
+        self.superscript.insert(index, value)
+    def replace_superscript_at(self, index, value):
+        self.superscript[index] = value
+    def get_center(self):
+        return self.center
+    def set_center(self, center):
+        self.center = center
+    def add_center(self, value):
+        self.center.append(value)
+    def insert_center_at(self, index, value):
+        self.center.insert(index, value)
+    def replace_center_at(self, index, value):
+        self.center[index] = value
+    def get_small(self):
+        return self.small
+    def set_small(self, small):
+        self.small = small
+    def add_small(self, value):
+        self.small.append(value)
+    def insert_small_at(self, index, value):
+        self.small.insert(index, value)
+    def replace_small_at(self, index, value):
+        self.small[index] = value
+    def get_cite(self):
+        return self.cite
+    def set_cite(self, cite):
+        self.cite = cite
+    def add_cite(self, value):
+        self.cite.append(value)
+    def insert_cite_at(self, index, value):
+        self.cite.insert(index, value)
+    def replace_cite_at(self, index, value):
+        self.cite[index] = value
+    def get_del(self):
+        return self.del_
+    def set_del(self, del_):
+        self.del_ = del_
+    def add_del(self, value):
+        self.del_.append(value)
+    def insert_del_at(self, index, value):
+        self.del_.insert(index, value)
+    def replace_del_at(self, index, value):
+        self.del_[index] = value
+    def get_ins(self):
+        return self.ins
+    def set_ins(self, ins):
+        self.ins = ins
+    def add_ins(self, value):
+        self.ins.append(value)
+    def insert_ins_at(self, index, value):
+        self.ins.insert(index, value)
+    def replace_ins_at(self, index, value):
+        self.ins[index] = value
+    def get_details(self):
+        return self.details
+    def set_details(self, details):
+        self.details = details
+    def add_details(self, value):
+        self.details.append(value)
+    def insert_details_at(self, index, value):
+        self.details.insert(index, value)
+    def replace_details_at(self, index, value):
+        self.details[index] = value
+    def get_summary(self):
+        return self.summary
+    def set_summary(self, summary):
+        self.summary = summary
+    def add_summary(self, value):
+        self.summary.append(value)
+    def insert_summary_at(self, index, value):
+        self.summary.insert(index, value)
+    def replace_summary_at(self, index, value):
+        self.summary[index] = value
+    def get_htmlonly(self):
+        return self.htmlonly
+    def set_htmlonly(self, htmlonly):
+        self.htmlonly = htmlonly
+    def add_htmlonly(self, value):
+        self.htmlonly.append(value)
+    def insert_htmlonly_at(self, index, value):
+        self.htmlonly.insert(index, value)
+    def replace_htmlonly_at(self, index, value):
+        self.htmlonly[index] = value
+    def get_manonly(self):
+        return self.manonly
+    def set_manonly(self, manonly):
+        self.manonly = manonly
+    def add_manonly(self, value):
+        self.manonly.append(value)
+    def insert_manonly_at(self, index, value):
+        self.manonly.insert(index, value)
+    def replace_manonly_at(self, index, value):
+        self.manonly[index] = value
+    def get_xmlonly(self):
+        return self.xmlonly
+    def set_xmlonly(self, xmlonly):
+        self.xmlonly = xmlonly
+    def add_xmlonly(self, value):
+        self.xmlonly.append(value)
+    def insert_xmlonly_at(self, index, value):
+        self.xmlonly.insert(index, value)
+    def replace_xmlonly_at(self, index, value):
+        self.xmlonly[index] = value
+    def get_rtfonly(self):
+        return self.rtfonly
+    def set_rtfonly(self, rtfonly):
+        self.rtfonly = rtfonly
+    def add_rtfonly(self, value):
+        self.rtfonly.append(value)
+    def insert_rtfonly_at(self, index, value):
+        self.rtfonly.insert(index, value)
+    def replace_rtfonly_at(self, index, value):
+        self.rtfonly[index] = value
+    def get_latexonly(self):
+        return self.latexonly
+    def set_latexonly(self, latexonly):
+        self.latexonly = latexonly
+    def add_latexonly(self, value):
+        self.latexonly.append(value)
+    def insert_latexonly_at(self, index, value):
+        self.latexonly.insert(index, value)
+    def replace_latexonly_at(self, index, value):
+        self.latexonly[index] = value
+    def get_docbookonly(self):
+        return self.docbookonly
+    def set_docbookonly(self, docbookonly):
+        self.docbookonly = docbookonly
+    def add_docbookonly(self, value):
+        self.docbookonly.append(value)
+    def insert_docbookonly_at(self, index, value):
+        self.docbookonly.insert(index, value)
+    def replace_docbookonly_at(self, index, value):
+        self.docbookonly[index] = value
+    def get_image(self):
+        return self.image
+    def set_image(self, image):
+        self.image = image
+    def add_image(self, value):
+        self.image.append(value)
+    def insert_image_at(self, index, value):
+        self.image.insert(index, value)
+    def replace_image_at(self, index, value):
+        self.image[index] = value
+    def get_dot(self):
+        return self.dot
+    def set_dot(self, dot):
+        self.dot = dot
+    def add_dot(self, value):
+        self.dot.append(value)
+    def insert_dot_at(self, index, value):
+        self.dot.insert(index, value)
+    def replace_dot_at(self, index, value):
+        self.dot[index] = value
+    def get_msc(self):
+        return self.msc
+    def set_msc(self, msc):
+        self.msc = msc
+    def add_msc(self, value):
+        self.msc.append(value)
+    def insert_msc_at(self, index, value):
+        self.msc.insert(index, value)
+    def replace_msc_at(self, index, value):
+        self.msc[index] = value
+    def get_plantuml(self):
+        return self.plantuml
+    def set_plantuml(self, plantuml):
+        self.plantuml = plantuml
+    def add_plantuml(self, value):
+        self.plantuml.append(value)
+    def insert_plantuml_at(self, index, value):
+        self.plantuml.insert(index, value)
+    def replace_plantuml_at(self, index, value):
+        self.plantuml[index] = value
+    def get_anchor(self):
+        return self.anchor
+    def set_anchor(self, anchor):
+        self.anchor = anchor
+    def add_anchor(self, value):
+        self.anchor.append(value)
+    def insert_anchor_at(self, index, value):
+        self.anchor.insert(index, value)
+    def replace_anchor_at(self, index, value):
+        self.anchor[index] = value
+    def get_formula(self):
+        return self.formula
+    def set_formula(self, formula):
+        self.formula = formula
+    def add_formula(self, value):
+        self.formula.append(value)
+    def insert_formula_at(self, index, value):
+        self.formula.insert(index, value)
+    def replace_formula_at(self, index, value):
+        self.formula[index] = value
+    def get_ref(self):
+        return self.ref
+    def set_ref(self, ref):
+        self.ref = ref
+    def add_ref(self, value):
+        self.ref.append(value)
+    def insert_ref_at(self, index, value):
+        self.ref.insert(index, value)
+    def replace_ref_at(self, index, value):
+        self.ref[index] = value
+    def get_emoji(self):
+        return self.emoji
+    def set_emoji(self, emoji):
+        self.emoji = emoji
+    def add_emoji(self, value):
+        self.emoji.append(value)
+    def insert_emoji_at(self, index, value):
+        self.emoji.insert(index, value)
+    def replace_emoji_at(self, index, value):
+        self.emoji[index] = value
+    def get_linebreak(self):
+        return self.linebreak
+    def set_linebreak(self, linebreak):
+        self.linebreak = linebreak
+    def add_linebreak(self, value):
+        self.linebreak.append(value)
+    def insert_linebreak_at(self, index, value):
+        self.linebreak.insert(index, value)
+    def replace_linebreak_at(self, index, value):
+        self.linebreak[index] = value
+    def get_id(self):
+        return self.id
+    def set_id(self, id):
+        self.id = id
+    def get_valueOf_(self): return self.valueOf_
+    def set_valueOf_(self, valueOf_): self.valueOf_ = valueOf_
+    def hasContent_(self):
+        if (
+            self.ulink or
+            self.bold or
+            self.s or
+            self.strike or
+            self.underline or
+            self.emphasis or
+            self.computeroutput or
+            self.subscript or
+            self.superscript or
+            self.center or
+            self.small or
+            self.cite or
+            self.del_ or
+            self.ins or
+            self.details or
+            self.summary or
+            self.htmlonly or
+            self.manonly or
+            self.xmlonly or
+            self.rtfonly or
+            self.latexonly or
+            self.docbookonly or
+            self.image or
+            self.dot or
+            self.msc or
+            self.plantuml or
+            self.anchor or
+            self.formula or
+            self.ref or
+            self.emoji or
+            self.linebreak or
+            (1 if type(self.valueOf_) in [int,float] else self.valueOf_) or
+            self.content_
+        ):
+            return True
+        else:
+            return False
+    def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='docTocItemType', pretty_print=True):
+        imported_ns_def_ = GenerateDSNamespaceDefs_.get('docTocItemType')
+        if imported_ns_def_ is not None:
+            namespacedef_ = imported_ns_def_
+        if pretty_print:
+            eol_ = '\n'
+        else:
+            eol_ = ''
+        if self.original_tagname_ is not None and name_ == 'docTocItemType':
+            name_ = self.original_tagname_
+        if UseCapturedNS_ and self.ns_prefix_:
+            namespaceprefix_ = self.ns_prefix_ + ':'
+        showIndent(outfile, level, pretty_print)
+        outfile.write('<%s%s%s' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+        already_processed = set()
+        self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='docTocItemType')
+        if self.hasContent_():
+            outfile.write('>%s' % (eol_, ))
+            self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='docTocItemType', pretty_print=pretty_print)
+            showIndent(outfile, level, pretty_print)
+            outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+        else:
+            outfile.write('/>%s' % (eol_, ))
+    def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='docTocItemType'):
+        if self.id is not None and 'id' not in already_processed:
+            already_processed.add('id')
+            outfile.write(' id=%s' % (self.gds_encode(self.gds_format_string(quote_attrib(self.id), input_name='id')), ))
+    def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='docTocItemType', fromsubclass_=False, pretty_print=True):
+        if not fromsubclass_:
+            for item_ in self.content_:
+                item_.export(outfile, level, item_.name, namespaceprefix_, pretty_print=pretty_print)
+        if pretty_print:
+            eol_ = '\n'
+        else:
+            eol_ = ''
+        for ulink_ in self.ulink:
+            namespaceprefix_ = self.ulink_nsprefix_ + ':' if (UseCapturedNS_ and self.ulink_nsprefix_) else ''
+            ulink_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ulink', pretty_print=pretty_print)
+        for bold_ in self.bold:
+            namespaceprefix_ = self.bold_nsprefix_ + ':' if (UseCapturedNS_ and self.bold_nsprefix_) else ''
+            bold_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='bold', pretty_print=pretty_print)
+        for s_ in self.s:
+            namespaceprefix_ = self.s_nsprefix_ + ':' if (UseCapturedNS_ and self.s_nsprefix_) else ''
+            s_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='s', pretty_print=pretty_print)
+        for strike_ in self.strike:
+            namespaceprefix_ = self.strike_nsprefix_ + ':' if (UseCapturedNS_ and self.strike_nsprefix_) else ''
+            strike_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='strike', pretty_print=pretty_print)
+        for underline_ in self.underline:
+            namespaceprefix_ = self.underline_nsprefix_ + ':' if (UseCapturedNS_ and self.underline_nsprefix_) else ''
+            underline_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='underline', pretty_print=pretty_print)
+        for emphasis_ in self.emphasis:
+            namespaceprefix_ = self.emphasis_nsprefix_ + ':' if (UseCapturedNS_ and self.emphasis_nsprefix_) else ''
+            emphasis_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='emphasis', pretty_print=pretty_print)
+        for computeroutput_ in self.computeroutput:
+            namespaceprefix_ = self.computeroutput_nsprefix_ + ':' if (UseCapturedNS_ and self.computeroutput_nsprefix_) else ''
+            computeroutput_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='computeroutput', pretty_print=pretty_print)
+        for subscript_ in self.subscript:
+            namespaceprefix_ = self.subscript_nsprefix_ + ':' if (UseCapturedNS_ and self.subscript_nsprefix_) else ''
+            subscript_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='subscript', pretty_print=pretty_print)
+        for superscript_ in self.superscript:
+            namespaceprefix_ = self.superscript_nsprefix_ + ':' if (UseCapturedNS_ and self.superscript_nsprefix_) else ''
+            superscript_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='superscript', pretty_print=pretty_print)
+        for center_ in self.center:
+            namespaceprefix_ = self.center_nsprefix_ + ':' if (UseCapturedNS_ and self.center_nsprefix_) else ''
+            center_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='center', pretty_print=pretty_print)
+        for small_ in self.small:
+            namespaceprefix_ = self.small_nsprefix_ + ':' if (UseCapturedNS_ and self.small_nsprefix_) else ''
+            small_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='small', pretty_print=pretty_print)
+        for cite_ in self.cite:
+            namespaceprefix_ = self.cite_nsprefix_ + ':' if (UseCapturedNS_ and self.cite_nsprefix_) else ''
+            cite_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='cite', pretty_print=pretty_print)
+        for del_ in self.del_:
+            namespaceprefix_ = self.del__nsprefix_ + ':' if (UseCapturedNS_ and self.del__nsprefix_) else ''
+            del_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='del', pretty_print=pretty_print)
+        for ins_ in self.ins:
+            namespaceprefix_ = self.ins_nsprefix_ + ':' if (UseCapturedNS_ and self.ins_nsprefix_) else ''
+            ins_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ins', pretty_print=pretty_print)
+        for details_ in self.details:
+            namespaceprefix_ = self.details_nsprefix_ + ':' if (UseCapturedNS_ and self.details_nsprefix_) else ''
+            details_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='details', pretty_print=pretty_print)
+        for summary_ in self.summary:
+            namespaceprefix_ = self.summary_nsprefix_ + ':' if (UseCapturedNS_ and self.summary_nsprefix_) else ''
+            summary_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='summary', pretty_print=pretty_print)
+        for htmlonly_ in self.htmlonly:
+            namespaceprefix_ = self.htmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.htmlonly_nsprefix_) else ''
+            htmlonly_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='htmlonly', pretty_print=pretty_print)
+        for manonly_ in self.manonly:
+            namespaceprefix_ = self.manonly_nsprefix_ + ':' if (UseCapturedNS_ and self.manonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%smanonly>%s</%smanonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(manonly_), input_name='manonly')), namespaceprefix_ , eol_))
+        for xmlonly_ in self.xmlonly:
+            namespaceprefix_ = self.xmlonly_nsprefix_ + ':' if (UseCapturedNS_ and self.xmlonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%sxmlonly>%s</%sxmlonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(xmlonly_), input_name='xmlonly')), namespaceprefix_ , eol_))
+        for rtfonly_ in self.rtfonly:
+            namespaceprefix_ = self.rtfonly_nsprefix_ + ':' if (UseCapturedNS_ and self.rtfonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%srtfonly>%s</%srtfonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(rtfonly_), input_name='rtfonly')), namespaceprefix_ , eol_))
+        for latexonly_ in self.latexonly:
+            namespaceprefix_ = self.latexonly_nsprefix_ + ':' if (UseCapturedNS_ and self.latexonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%slatexonly>%s</%slatexonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(latexonly_), input_name='latexonly')), namespaceprefix_ , eol_))
+        for docbookonly_ in self.docbookonly:
+            namespaceprefix_ = self.docbookonly_nsprefix_ + ':' if (UseCapturedNS_ and self.docbookonly_nsprefix_) else ''
+            showIndent(outfile, level, pretty_print)
+            outfile.write('<%sdocbookonly>%s</%sdocbookonly>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(docbookonly_), input_name='docbookonly')), namespaceprefix_ , eol_))
+        for image_ in self.image:
+            namespaceprefix_ = self.image_nsprefix_ + ':' if (UseCapturedNS_ and self.image_nsprefix_) else ''
+            image_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='image', pretty_print=pretty_print)
+        for dot_ in self.dot:
+            namespaceprefix_ = self.dot_nsprefix_ + ':' if (UseCapturedNS_ and self.dot_nsprefix_) else ''
+            dot_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='dot', pretty_print=pretty_print)
+        for msc_ in self.msc:
+            namespaceprefix_ = self.msc_nsprefix_ + ':' if (UseCapturedNS_ and self.msc_nsprefix_) else ''
+            msc_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='msc', pretty_print=pretty_print)
+        for plantuml_ in self.plantuml:
+            namespaceprefix_ = self.plantuml_nsprefix_ + ':' if (UseCapturedNS_ and self.plantuml_nsprefix_) else ''
+            plantuml_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='plantuml', pretty_print=pretty_print)
+        for anchor_ in self.anchor:
+            namespaceprefix_ = self.anchor_nsprefix_ + ':' if (UseCapturedNS_ and self.anchor_nsprefix_) else ''
+            anchor_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='anchor', pretty_print=pretty_print)
+        for formula_ in self.formula:
+            namespaceprefix_ = self.formula_nsprefix_ + ':' if (UseCapturedNS_ and self.formula_nsprefix_) else ''
+            formula_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='formula', pretty_print=pretty_print)
+        for ref_ in self.ref:
+            namespaceprefix_ = self.ref_nsprefix_ + ':' if (UseCapturedNS_ and self.ref_nsprefix_) else ''
+            ref_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='ref', pretty_print=pretty_print)
+        for emoji_ in self.emoji:
+            namespaceprefix_ = self.emoji_nsprefix_ + ':' if (UseCapturedNS_ and self.emoji_nsprefix_) else ''
+            emoji_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='emoji', pretty_print=pretty_print)
+        for linebreak_ in self.linebreak:
+            namespaceprefix_ = self.linebreak_nsprefix_ + ':' if (UseCapturedNS_ and self.linebreak_nsprefix_) else ''
+            linebreak_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='linebreak', pretty_print=pretty_print)
+    def build(self, node, gds_collector_=None):
+        self.gds_collector_ = gds_collector_
+        if SaveElementTreeNode:
+            self.gds_elementtree_node_ = node
+        already_processed = set()
+        self.ns_prefix_ = node.prefix
+        self.buildAttributes(node, node.attrib, already_processed)
+        self.valueOf_ = get_all_text_(node)
+        if node.text is not None:
+            obj_ = self.mixedclass_(MixedContainer.CategoryText,
+                MixedContainer.TypeNone, '', node.text)
+            self.content_.append(obj_)
+        for child in node:
+            nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+            self.buildChildren(child, node, nodeName_, gds_collector_=gds_collector_)
+        return self
+    def buildAttributes(self, node, attrs, already_processed):
+        value = find_attr_value_('id', node)
+        if value is not None and 'id' not in already_processed:
+            already_processed.add('id')
+            self.id = value
+    def buildChildren(self, child_, node, nodeName_, fromsubclass_=False, gds_collector_=None):
+        if nodeName_ == 'ulink':
+            obj_ = docURLLink.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'ulink', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_ulink'):
+              self.add_ulink(obj_.value)
+            elif hasattr(self, 'set_ulink'):
+              self.set_ulink(obj_.value)
+        elif nodeName_ == 'bold':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'bold', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_bold'):
+              self.add_bold(obj_.value)
+            elif hasattr(self, 'set_bold'):
+              self.set_bold(obj_.value)
+        elif nodeName_ == 's':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 's', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_s'):
+              self.add_s(obj_.value)
+            elif hasattr(self, 'set_s'):
+              self.set_s(obj_.value)
+        elif nodeName_ == 'strike':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'strike', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_strike'):
+              self.add_strike(obj_.value)
+            elif hasattr(self, 'set_strike'):
+              self.set_strike(obj_.value)
+        elif nodeName_ == 'underline':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'underline', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_underline'):
+              self.add_underline(obj_.value)
+            elif hasattr(self, 'set_underline'):
+              self.set_underline(obj_.value)
+        elif nodeName_ == 'emphasis':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'emphasis', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_emphasis'):
+              self.add_emphasis(obj_.value)
+            elif hasattr(self, 'set_emphasis'):
+              self.set_emphasis(obj_.value)
+        elif nodeName_ == 'computeroutput':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'computeroutput', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_computeroutput'):
+              self.add_computeroutput(obj_.value)
+            elif hasattr(self, 'set_computeroutput'):
+              self.set_computeroutput(obj_.value)
+        elif nodeName_ == 'subscript':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'subscript', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_subscript'):
+              self.add_subscript(obj_.value)
+            elif hasattr(self, 'set_subscript'):
+              self.set_subscript(obj_.value)
+        elif nodeName_ == 'superscript':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'superscript', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_superscript'):
+              self.add_superscript(obj_.value)
+            elif hasattr(self, 'set_superscript'):
+              self.set_superscript(obj_.value)
+        elif nodeName_ == 'center':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'center', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_center'):
+              self.add_center(obj_.value)
+            elif hasattr(self, 'set_center'):
+              self.set_center(obj_.value)
+        elif nodeName_ == 'small':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'small', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_small'):
+              self.add_small(obj_.value)
+            elif hasattr(self, 'set_small'):
+              self.set_small(obj_.value)
+        elif nodeName_ == 'cite':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'cite', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_cite'):
+              self.add_cite(obj_.value)
+            elif hasattr(self, 'set_cite'):
+              self.set_cite(obj_.value)
+        elif nodeName_ == 'del':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'del', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_del'):
+              self.add_del(obj_.value)
+            elif hasattr(self, 'set_del'):
+              self.set_del(obj_.value)
+        elif nodeName_ == 'ins':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'ins', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_ins'):
+              self.add_ins(obj_.value)
+            elif hasattr(self, 'set_ins'):
+              self.set_ins(obj_.value)
+        elif nodeName_ == 'details':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'details', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_details'):
+              self.add_details(obj_.value)
+            elif hasattr(self, 'set_details'):
+              self.set_details(obj_.value)
+        elif nodeName_ == 'summary':
+            obj_ = docMarkupType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'summary', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_summary'):
+              self.add_summary(obj_.value)
+            elif hasattr(self, 'set_summary'):
+              self.set_summary(obj_.value)
+        elif nodeName_ == 'htmlonly':
+            obj_ = docHtmlOnlyType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'htmlonly', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_htmlonly'):
+              self.add_htmlonly(obj_.value)
+            elif hasattr(self, 'set_htmlonly'):
+              self.set_htmlonly(obj_.value)
+        elif nodeName_ == 'manonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'manonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'manonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'manonly', valuestr_)
+            self.content_.append(obj_)
+            self.manonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'xmlonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'xmlonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'xmlonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'xmlonly', valuestr_)
+            self.content_.append(obj_)
+            self.xmlonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'rtfonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'rtfonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'rtfonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'rtfonly', valuestr_)
+            self.content_.append(obj_)
+            self.rtfonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'latexonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'latexonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'latexonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'latexonly', valuestr_)
+            self.content_.append(obj_)
+            self.latexonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'docbookonly' and child_.text is not None:
+            valuestr_ = child_.text
+            valuestr_ = self.gds_parse_string(valuestr_, node, 'docbookonly')
+            valuestr_ = self.gds_validate_string(valuestr_, node, 'docbookonly')
+            obj_ = self.mixedclass_(MixedContainer.CategorySimple,
+                MixedContainer.TypeString, 'docbookonly', valuestr_)
+            self.content_.append(obj_)
+            self.docbookonly_nsprefix_ = child_.prefix
+        elif nodeName_ == 'image':
+            obj_ = docImageType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'image', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_image'):
+              self.add_image(obj_.value)
+            elif hasattr(self, 'set_image'):
+              self.set_image(obj_.value)
+        elif nodeName_ == 'dot':
+            obj_ = docDotMscType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'dot', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_dot'):
+              self.add_dot(obj_.value)
+            elif hasattr(self, 'set_dot'):
+              self.set_dot(obj_.value)
+        elif nodeName_ == 'msc':
+            obj_ = docDotMscType.factory(parent_object_=self)
+            obj_.build(child_, gds_collector_=gds_collector_)
+            obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
+                MixedContainer.TypeNone, 'msc', obj_)
+            self.content_.append(obj_)
+            if hasattr(self, 'add_msc'):
+              self.add_msc(obj_.value)
+            elif hasattr(self, 'set_msc'):
+              self.set_msc(obj_.value)
+        elif nodeName_ == 'plantuml':
+            obj_ = docPlantumlType.factory(parent_object_=self)
             obj_.build(child_, gds_collector_=gds_collector_)
             obj_ = self.mixedclass_(MixedContainer.CategoryComplex,
                 MixedContainer.TypeNone, 'plantuml', obj_)
@@ -22288,12 +26569,14 @@ __all__ = [
     "docBlockQuoteType",
     "docCaptionType",
     "docCopyType",
+    "docDotMscType",
     "docEmojiType",
     "docEmptyType",
     "docEntryType",
     "docFormulaType",
     "docHeadingType",
     "docHtmlOnlyType",
+    "docImageFileType",
     "docImageType",
     "docIndexEntryType",
     "docInternalS1Type",
@@ -22312,6 +26595,7 @@ __all__ = [
     "docParamName",
     "docParamNameList",
     "docParamType",
+    "docPlantumlType",
     "docRefTextType",
     "docRowType",
     "docSect1Type",
@@ -22343,6 +26627,7 @@ __all__ = [
     "name",
     "nodeType",
     "paramType",
+    "qualifiedname",
     "read",
     "refTextType",
     "refType",
index 5ef79c8..f30d66c 100644 (file)
@@ -3,19 +3,19 @@
 
 #
 # Generated  by generateDS.py.
-# Python 3.9.0 (default, Oct 27 2020, 14:15:17)  [Clang 12.0.0 (clang-1200.0.32.21)]
+#
 #
 # Command line options:
 #   ('--no-dates', '')
 #   ('--no-versions', '')
 #   ('-f', '')
-#   ('-o', '/Users/dimitri/doxygen.git/addon/doxmlparser/doxmlparser/index.py')
+#   ('-o', '.../addon/doxmlparser/doxmlparser/index.py')
 #
 # Command line arguments:
-#   /Users/dimitri/doxygen.git/templates/xml/index.xsd
+#  .../templates/xml/index.xsd
 #
 # Command line:
-#   /usr/local/bin/generateDS --no-dates --no-versions -f -o "/Users/dimitri/doxygen.git/addon/doxmlparser/doxmlparser/index.py" /Users/dimitri/doxygen.git/templates/xml/index.xsd
+#  .../generateDS --no-dates --no-versions -f -o ".../addon/doxmlparser/doxmlparser/index.py" .../templates/xml/index.xsd
 #
 # Current working directory (os.getcwd()):
 #   doxmlparser
@@ -175,7 +175,7 @@ except ModulenotfoundExp_ :
 try:
     from generatedssuper import GeneratedsSuper
 except ModulenotfoundExp_ as exp:
-    
+
     class GeneratedsSuper(object):
         __hash__ = object.__hash__
         tzoff_pattern = re_.compile(r'(\+|-)((0\d|1[0-3]):[0-5]\d|14:00)$')
@@ -657,8 +657,8 @@ except ModulenotfoundExp_ as exp:
                     self.gds_elementtree_node_.sourceline)
             else:
                 return ""
-    
-    
+
+
     def getSubclassFromModule_(module, class_):
         '''Get the subclass of a class from a specific module.'''
         name = class_.__name__ + 'Sub'
@@ -984,6 +984,7 @@ class CompoundKind(str, Enum):
     EXAMPLE='example'
     DIR='dir'
     TYPE='type'
+    CONCEPT='concept'
 
 
 class MemberKind(str, Enum):
@@ -1194,7 +1195,7 @@ class CompoundType(GeneratedsSuper):
                 self.gds_collector_.add_message('Value "%(value)s"%(lineno)s is not of the correct base simple type (str)' % {"value": value, "lineno": lineno, })
                 return False
             value = value
-            enumerations = ['class', 'struct', 'union', 'interface', 'protocol', 'category', 'exception', 'file', 'namespace', 'group', 'page', 'example', 'dir', 'type']
+            enumerations = ['class', 'struct', 'union', 'interface', 'protocol', 'category', 'exception', 'file', 'namespace', 'group', 'page', 'example', 'dir', 'type', 'concept']
             if value not in enumerations:
                 lineno = self.gds_get_node_lineno_()
                 self.gds_collector_.add_message('Value "%(value)s"%(lineno)s does not match xsd enumeration restriction on CompoundKind' % {"value" : encode_str_2_3(value), "lineno": lineno} )
diff --git a/addon/doxmlparser/generateDS_post.py b/addon/doxmlparser/generateDS_post.py
new file mode 100755 (executable)
index 0000000..6416b2c
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+#
+# Copyright (C) 1997-202i 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.
+
+import sys
+import re
+
+def main():
+    inputFile = open(sys.argv[1], 'r')
+    outputFile = open(sys.argv[2], 'wb')
+    lineStr = ""
+    for line in inputFile:
+        line = line.rstrip()
+        line = re.sub(r'# Python.*','#',line)
+        line = re.sub(r"('-o', ').*(/addon/doxmlparser/doxmlparser)","\\1...\\2",line)
+        # python 2 slips the u in ...
+        line = re.sub(r"u'","'",line)
+
+        if line.find("generateDS") == -1:
+            line = re.sub(r'(#  ).*(/templates/xml/)','\\1...\\2',line)
+        else:
+            line = re.sub(r'(#  ).*generateDS(.* -o ").*(/addon/doxmlparser/doxmlparser/.* ).*(/templates/xml/)',
+                           '\\1.../generateDS\\2...\\3...\\4',line)
+        outputFile.write(str.encode(line))
+        outputFile.write(str.encode('\n'))
+
+
+if __name__ == '__main__':
+    main()
index 9c10e51..a410ff5 100644 (file)
@@ -49,7 +49,7 @@ class XRefDummyCodeGenerator : public CodeOutputInterface
     // and cross-linked version of the source code, but who needs that anyway ;-)
     void codify(const QCString &) override {}
     void writeCodeLink(CodeSymbolType,const QCString &,const QCString &,const QCString &,const QCString &,const QCString &) override  {}
-    void writeLineNumber(const QCString &,const QCString &,const QCString &,int) override {}
+    void writeLineNumber(const QCString &,const QCString &,const QCString &,int,bool) override {}
     virtual void writeTooltip(const QCString &,const DocLinkInfo &,
                               const QCString &,const QCString &,const SourceLinkInfo &,
                               const SourceLinkInfo &) override {}
index a0ee1c6..beb21c8 100644 (file)
@@ -60,7 +60,7 @@ class Doxyparse : public CodeOutputInterface
     void writeCodeAnchor(const QCString &) override {}
     void startFontClass(const QCString &) override {}
     void endFontClass() override {}
-    void writeLineNumber(const QCString &,const QCString &,const QCString &,int) override {}
+    void writeLineNumber(const QCString &,const QCString &,const QCString &,int,bool) override {}
     virtual void writeTooltip(const QCString &,const DocLinkInfo &,
                               const QCString &,const QCString &,const SourceLinkInfo &,
                               const SourceLinkInfo &) override {}
index 26517bd..7b88807 100644 (file)
@@ -150,7 +150,7 @@ struct WordPosition
 /** Class representing the '<' operator for WordPosition objects based on position. */
 struct WordPosition_less
 {
-  bool operator()(const WordPosition &p1,const WordPosition &p2)
+  bool operator()(const WordPosition &p1,const WordPosition &p2) const
   {
     return p1.start<p2.start;
   }
@@ -167,7 +167,7 @@ struct Fragment
 /** Class representing the '>' operator for Fragment objects based on occurrence. */
 struct Fragment_greater
 {
-  bool operator()(const Fragment &p1,const Fragment &p2)
+  bool operator()(const Fragment &p1,const Fragment &p2) const
   {
     return p1.occurrences>p2.occurrences;
   }
index 6813a6d..63ac8e3 100644 (file)
@@ -114,6 +114,8 @@ ${doxywizard_RESOURCES_RCC}
 doxywizard.rc
 )
 
+set_property(TARGET doxywizard PROPERTY WIN32_EXECUTABLE true)
+
 if(Qt5Core_FOUND)
   target_link_libraries(doxywizard Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Xml doxygen_version)
 else()
index b93a79d..733ebc1 100644 (file)
@@ -23,7 +23,9 @@
  */
 #include "config.h"
 #include "input.h"
+#include "inputbool.h"
 #include "inputstring.h"
+#include "inputobsolete.h"
 #include "config_msg.h"
 
 #include <QString>
@@ -383,9 +385,7 @@ static void readIncludeFile(const QString &incName)
 %x      Start
 %x      SkipInvalid
 %x      GetString
-%x      GetEnum
 %x      GetStrList
-%x      GetQuotedString
 %x      Include
 
 %%
@@ -429,11 +429,29 @@ static void readIncludeFile(const QString &incName)
                                                 BEGIN(GetString);
                                                 break;
                                               case Input::Obsolete:
-                                                config_warn("Tag '%s' at line %d of file %s has become obsolete.\n"
-                                                           "To avoid this warning please update your configuration "
-                                                           "file using \"doxygen -u\"\n", qPrintable(g_cmd),
-                                                           yylineno,qPrintable(g_yyFileName));
-                                                BEGIN(SkipInvalid);
+                                                 {
+                                                   config_warn("Tag '%s' at line %d of file %s has become obsolete.\n"
+                                                       "To avoid this warning please update your configuration "
+                                                       "file using \"doxygen -u\"\n", qPrintable(g_cmd),
+                                                       yylineno,qPrintable(g_yyFileName));
+                                                   InputObsolete *obsoleteOpt = dynamic_cast<InputObsolete*>(g_curOption);
+                                                   if (obsoleteOpt)
+                                                   {
+                                                     if (obsoleteOpt->orgKind()==Input::StrList)
+                                                     {
+                                                       *g_arg = QStringList();
+                                                       BEGIN(GetStrList);
+                                                     }
+                                                     else
+                                                     {
+                                                       BEGIN(GetString);
+                                                     }
+                                                   }
+                                                   else
+                                                   {
+                                                     BEGIN(SkipInvalid);
+                                                   }
+                                                 }
                                                 break;
                                             }
                                           }
@@ -464,12 +482,24 @@ static void readIncludeFile(const QString &incName)
                                                BEGIN(SkipInvalid);
                                                break;
                                              case Input::Obsolete:
-                                                config_warn("Tag '%s' at line %d of file %s has become obsolete.\n"
-                                                           "To avoid this warning please update your configuration "
-                                                           "file using \"doxygen -u\"\n",
-                                                           qPrintable(g_cmd),yylineno,qPrintable(g_yyFileName));
-                                                BEGIN(SkipInvalid);
-                                                break;
+                                                {
+                                                 config_warn("Tag '%s' at line %d of file %s has become obsolete.\n"
+                                                             "To avoid this warning please update your configuration "
+                                                             "file using \"doxygen -u\"\n",
+                                                             qPrintable(g_cmd),yylineno,qPrintable(g_yyFileName));
+                                                   InputObsolete *obsoleteOpt = dynamic_cast<InputObsolete*>(g_curOption);
+                                                   if (obsoleteOpt && obsoleteOpt->orgKind()==Input::StrList)
+                                                   {
+                                                    g_arg = &g_curOption->value();
+                                                    g_str=QByteArray();
+                                                     BEGIN(GetStrList);
+                                                   }
+                                                  else
+                                                   {
+                                                     BEGIN(SkipInvalid);
+                                                   }
+                                                }
+                                               break;
                                             }
                                           }
                                        }
@@ -662,6 +692,39 @@ static void substEnvVarsInStrList(QStringList &sl)
 
 //--------------------------------------------------------------------------
 
+static void upgradeConfig(const QHash<QString,Input*> &options)
+{
+  auto it1 = options.find(QString::fromLatin1("CLASS_DIAGRAMS"));
+  auto it2 = options.find(QString::fromLatin1("HAVE_DOT"));
+  auto it3 = options.find(QString::fromLatin1("CLASS_GRAPH"));
+  if (it1!=options.end() && it2!=options.end() && it3!=options.end())
+  {
+    if ((*it1)->kind()==Input::Obsolete)
+    {
+      InputObsolete *optClassDiagram = dynamic_cast<InputObsolete*>(*it1);
+      InputBool     *optHaveDot      = dynamic_cast<InputBool*>    (*it2);
+      InputString   *optClassGraph   = dynamic_cast<InputString*>  (*it3);
+      if (optClassDiagram->orgKind()==Input::Bool)
+      {
+        const QVariant &v1 = optClassDiagram->value();
+        const QVariant &v2 = optHaveDot->value();
+        QVariant &v3 = optClassGraph->value();
+        bool isValid1=false,isValid2=false,isValid3=false;
+        bool classDiagrams = InputBool::convertToBool(v1,isValid1);
+        bool haveDot       = InputBool::convertToBool(v2,isValid2);
+        bool classGraph    = InputBool::convertToBool(v3,isValid3);
+        if (isValid1 && isValid2 && isValid3 && !classDiagrams && !haveDot && classGraph)
+        {
+         config_warn("Changing CLASS_GRAPH option to TEXT because obsolete option CLASS_DIAGRAM was found and set to NO.\n");
+          optClassGraph->setValue(QString::fromLatin1("TEXT"));
+        }
+      }
+    }
+  }
+}
+
+//--------------------------------------------------------------------------
+
 bool parseConfig(
       const QString &fileName,
       const QHash<QString,Input *> &options
@@ -693,6 +756,8 @@ bool parseConfig(
   BEGIN( Start );
   config_doxywYYlex();
 
+  upgradeConfig(options);
+
   // update the values in the UI
   i.toFront();
   while (i.hasNext())
index a50ff2b..2a1685b 100644 (file)
@@ -3,8 +3,8 @@
  * 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,6 +16,7 @@
 #include "inputint.h"
 #include "inputstring.h"
 #include "inputstrlist.h"
+#include "inputobsolete.h"
 #include "config.h"
 #include "version.h"
 #include "configdoc.h"
@@ -40,7 +41,7 @@
 
 static QString convertToComment(const QString &s)
 {
-  if (s.isEmpty()) 
+  if (s.isEmpty())
   {
     return QString();
   }
@@ -122,7 +123,7 @@ Expert::Expert()
 Expert::~Expert()
 {
   QHashIterator<QString,Input*> i(m_options);
-  while (i.hasNext()) 
+  while (i.hasNext())
   {
     i.next();
     delete i.value();
@@ -388,7 +389,7 @@ static QString getDocsForNode(const QDomElement &child)
       }
     }
   }
-  
+
   if (child.hasAttribute(SA("depends")))
   {
     QString dependsOn = child.attribute(SA("depends"));
@@ -509,7 +510,7 @@ QWidget *Expert::createTopicWidget(QDomElement &elem)
       QString docs = getDocsForNode(child);
       if (type==SA("bool"))
       {
-        InputBool *boolOption = 
+        InputBool *boolOption =
           new InputBool(
               layout,row,
               child.attribute(SA("id")),
@@ -535,6 +536,10 @@ QWidget *Expert::createTopicWidget(QDomElement &elem)
         {
           mode = InputString::StringFile;
         }
+        else if (format==SA("filedir"))
+        {
+          mode = InputString::StringFileDir;
+        }
         else if (format==SA("image"))
         {
           mode = InputString::StringImage;
@@ -543,7 +548,7 @@ QWidget *Expert::createTopicWidget(QDomElement &elem)
         {
           mode = InputString::StringFree;
         }
-        InputString *stringOption = 
+        InputString *stringOption =
           new InputString(
               layout,row,
               child.attribute(SA("id")),
@@ -585,7 +590,7 @@ QWidget *Expert::createTopicWidget(QDomElement &elem)
       }
       else if (type==SA("int"))
       {
-        InputInt *intOption = 
+        InputInt *intOption =
           new InputInt(
               layout,row,
               child.attribute(SA("id")),
@@ -631,7 +636,7 @@ QWidget *Expert::createTopicWidget(QDomElement &elem)
           }
           listVal = listVal.nextSiblingElement();
         }
-        InputStrList *listOption = 
+        InputStrList *listOption =
           new InputStrList(
               layout,row,
               child.attribute(SA("id")),
@@ -648,6 +653,31 @@ QWidget *Expert::createTopicWidget(QDomElement &elem)
       }
       else if (type==SA("obsolete"))
       {
+        Input::Kind orgKind;
+        QString orgKindStr = child.attribute(SA("orgtype"));
+        if (orgKindStr==SA("int"))
+        {
+          orgKind = Input::Int;
+        }
+        else if (orgKindStr==SA("bool"))
+        {
+          orgKind = Input::Bool;
+        }
+        else if (orgKindStr==SA("string") || orgKindStr==SA("enum"))
+        {
+          orgKind = Input::String;
+        }
+        else if (orgKindStr==SA("strlist"))
+        {
+          orgKind = Input::StrList;
+        }
+        else
+        {
+          orgKind = Input::Obsolete;
+        }
+        InputObsolete *obsoleteOption =
+          new InputObsolete(child.attribute(SA("id")),orgKind);
+        m_options.insert(child.attribute(SA("id")),obsoleteOption);
         // ignore
       }
       else // should not happen
@@ -665,7 +695,7 @@ QWidget *Expert::createTopicWidget(QDomElement &elem)
     QString setting = child.attribute(SA("setting"));
     QString dependsOn = child.attribute(SA("depends"));
     QString id        = child.attribute(SA("id"));
-    if (!dependsOn.isEmpty() && 
+    if (!dependsOn.isEmpty() &&
         (setting.isEmpty() || IS_SUPPORTED(setting.toLatin1())))
     {
        Input *parentOption = m_options[dependsOn];
@@ -690,7 +720,7 @@ QWidget *Expert::createTopicWidget(QDomElement &elem)
 
   // set initial dependencies
   QHashIterator<QString,Input*> i(m_options);
-  while (i.hasNext()) 
+  while (i.hasNext())
   {
     i.next();
     if (i.value())
@@ -714,7 +744,7 @@ void Expert::activateTopic(QTreeWidgetItem *item,QTreeWidgetItem *)
   {
     QWidget *w = m_topics[item->text(0)];
     m_topicStack->setCurrentWidget(w);
-    m_prev->setEnabled(m_topicStack->currentIndex()!=0); 
+    m_prev->setEnabled(m_topicStack->currentIndex()!=0);
     m_next->setEnabled(true);
   }
 }
@@ -722,11 +752,11 @@ void Expert::activateTopic(QTreeWidgetItem *item,QTreeWidgetItem *)
 void Expert::loadSettings(QSettings *s)
 {
   QHashIterator<QString,Input*> i(m_options);
-  while (i.hasNext()) 
+  while (i.hasNext())
   {
     i.next();
     QVariant var = s->value(SA("config/")+i.key());
-    if (i.value())
+    if (i.value() && var.isValid())
     {
       //printf("Loading key %s: type=%d value='%s'\n",qPrintable(i.key()),var.type(),qPrintable(var.toString()));
       i.value()->value() = var;
@@ -738,7 +768,7 @@ void Expert::loadSettings(QSettings *s)
 void Expert::saveSettings(QSettings *s)
 {
   QHashIterator<QString,Input*> i(m_options);
-  while (i.hasNext()) 
+  while (i.hasNext())
   {
     i.next();
     //printf("Saving key %s: type=%d value='%s'\n",qPrintable(i.key()),i.value()->value().type(),qPrintable(i.value()->value().toString()));
@@ -781,23 +811,26 @@ void Expert::saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec,
       if (i!=m_options.end())
       {
         Input *option = i.value();
-        if (option && !brief)
+        if (option->kind()!=Input::Obsolete)
         {
-          t << "\n";
-          t << convertToComment(option->templateDocs());
-          t << "\n";
-        }
-        bool toPrint = true;
-        if (option && condensed) toPrint = !option->isDefault();
-        if (toPrint)
-        {
-          t << name.leftJustified(MAX_OPTION_LENGTH) << "=";
-          if (option && !option->isEmpty())
+          if (option && !brief)
           {
-            t << " ";
-            option->writeValue(t,codec);
+            t << "\n";
+            t << convertToComment(option->templateDocs());
+            t << "\n";
+          }
+          bool toPrint = true;
+          if (option && condensed) toPrint = !option->isDefault();
+          if (toPrint)
+          {
+            t << name.leftJustified(MAX_OPTION_LENGTH) << "=";
+            if (option && !option->isEmpty())
+            {
+              t << " ";
+              option->writeValue(t,codec);
+            }
+            t << "\n";
           }
-          t << "\n";
         }
       }
     }
@@ -890,7 +923,7 @@ void Expert::resetToDefaults()
 {
   //printf("Expert::makeDefaults()\n");
   QHashIterator<QString,Input*> i(m_options);
-  while (i.hasNext()) 
+  while (i.hasNext())
   {
     i.next();
     if (i.value())
@@ -904,7 +937,7 @@ static bool stringVariantToBool(const QVariant &v)
 {
   QString s = v.toString().toLower();
   return s==QString::fromLatin1("yes") || s==QString::fromLatin1("true") || s==QString::fromLatin1("1");
-} 
+}
 
 static bool getBoolOption(
     const QHash<QString,Input*>&model,const QString &name)
@@ -912,7 +945,7 @@ static bool getBoolOption(
   Input *option = model[name];
   Q_ASSERT(option!=0);
   return stringVariantToBool(option->value());
-} 
+}
 
 static QString getStringOption(
     const QHash<QString,Input*>&model,const QString &name)
@@ -944,7 +977,7 @@ QString Expert::getHtmlOutputIndex(const QString &workingDir) const
     indexFile = outputDir;
   }
   else // append
-  { 
+  {
     indexFile += QString::fromLatin1("/")+outputDir;
   }
   if (QFileInfo(htmlOutputDir).isAbsolute()) // override
index 132658d..bbe17ca 100644 (file)
@@ -89,18 +89,35 @@ QVariant &InputBool::value()
   return m_value;
 }
 
-void InputBool::update()
+bool InputBool::convertToBool(const QVariant &value,bool &isValid)
 {
-  QString v = m_value.toString().toLower();
+  QString v = value.toString().toLower();
   if (v==QString::fromLatin1("yes") || v==QString::fromLatin1("true") ||
       v==QString::fromLatin1("1")   || v==QString::fromLatin1("all"))
   {
-    m_state = true;
+    isValid = true;
+    return true;
   }
   else if (v==QString::fromLatin1("no") || v==QString::fromLatin1("false") ||
            v==QString::fromLatin1("0")  || v==QString::fromLatin1("none"))
   {
-    m_state = false;
+    isValid = true;
+    return false;
+  }
+  else
+  {
+    isValid = false;
+    return false;
+  }
+}
+
+void InputBool::update()
+{
+  bool isValid=false;
+  bool b = convertToBool(m_value,isValid);
+  if (isValid)
+  {
+    m_state = b;
   }
   else
   {
index baee2c4..e203df3 100644 (file)
@@ -3,8 +3,8 @@
  * 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.
  *
@@ -25,7 +25,7 @@ class InputBool : public QObject, public Input
   Q_OBJECT
 
   public:
-    InputBool(QGridLayout *layout,int &row,const QString &id, 
+    InputBool(QGridLayout *layout,int &row,const QString &id,
               bool enabled, const QString &docs );
 
     // Input
@@ -41,6 +41,7 @@ class InputBool : public QObject, public Input
     bool isDefault();
     void writeValue(QTextStream &t,QTextCodec *codec);
     void setTemplateDocs(const QString &docs) { m_tdocs = docs; }
+    static bool convertToBool(const QVariant &v,bool &isValid);
 
   public slots:
     void reset();
index d7021c4..1f6b79c 100644 (file)
@@ -3,8 +3,8 @@
  * 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,10 +26,10 @@ class InputInt : public QObject, public Input
 
   public:
     InputInt( QGridLayout *layout,int &row,
-              const QString &id, int defVal, 
+              const QString &id, int defVal,
               int minVal, int maxVal,
               const QString &docs );
-    ~InputInt(){};
+    ~InputInt() = default;
 
     // Input
     QVariant &value();
@@ -47,7 +47,7 @@ class InputInt : public QObject, public Input
 
   public slots:
     void reset();
-    void setValue(int val); 
+    void setValue(int val);
 
   private slots:
     void help();
diff --git a/addon/doxywizard/inputobsolete.h b/addon/doxywizard/inputobsolete.h
new file mode 100644 (file)
index 0000000..b8e33e5
--- /dev/null
@@ -0,0 +1,42 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1997-2021 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 INPUTOBSOLETE_H
+#define INPUTOBSOLETE_H
+
+class InputObsolete : public Input
+{
+  public:
+    InputObsolete(const QString &id, Kind orgKind) : m_id(id), m_orgKind(orgKind) {}
+    QVariant &value()            { return m_value; }
+    void update()                {}
+    Kind kind() const            { return Obsolete; }
+    QString docs() const         { return QString(); }
+    QString id() const           { return m_id; }
+    QString templateDocs() const { return QString(); }
+    void addDependency(Input *)  {}
+    void setEnabled(bool)        {}
+    void updateDependencies()    {}
+    void reset()                 {}
+    bool isDefault()             { return false; }
+    void writeValue(QTextStream &,QTextCodec *) {}
+    void setTemplateDocs(const QString &) {}
+    bool isEmpty()               { return false; };
+    Kind orgKind() const         { return m_orgKind; }
+  private:
+    QString   m_id;
+    Kind      m_orgKind;
+    QVariant  m_value;
+};
+
+#endif
+
index ac76342..8f09174 100644 (file)
@@ -3,8 +3,8 @@
  * 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.
  *
@@ -36,17 +36,19 @@ class NoWheelComboBox : public QComboBox
 
 
 InputString::InputString( QGridLayout *layout,int &row,
-                          const QString & id, const QString &s, 
+                          const QString & id, const QString &s,
                           StringMode m, const QString &docs,
                           const QString &absPath )
   : m_default(s), m_sm(m), m_index(0), m_docs(docs), m_id(id),
     m_absPath(absPath==QString::fromLatin1("1"))
 {
   m_lab = new HelpLabel(id);
+  m_brFile = 0;
+  m_brDir = 0;
   if (m==StringFixed)
   {
     layout->addWidget( m_lab, row, 0 );
-    m_com = new NoWheelComboBox; 
+    m_com = new NoWheelComboBox;
     layout->addWidget( m_com, row, 1, 1, 3, Qt::AlignLeft );
     m_le=0;
     m_br=0;
@@ -60,17 +62,17 @@ InputString::InputString( QGridLayout *layout,int &row,
     m_le->setText( s );
     m_im = 0;
     //layout->setColumnMinimumWidth(2,150);
-    if (m==StringFile || m==StringDir || m==StringImage)
+    if (m==StringFile || m==StringDir || m==StringImage || m==StringFileDir)
     {
-      layout->addWidget( m_le, row, 1 );
+      QHBoxLayout *rowLayout = new QHBoxLayout;
+      rowLayout->addWidget( m_le);
       m_br = new QToolBar;
       m_br->setIconSize(QSize(24,24));
-      if (m==StringFile || m==StringImage
+      if (m==StringFile || m==StringImage || m==StringFileDir)
       {
-        QAction *file = m_br->addAction(QIcon(QString::fromLatin1(":/images/file.png")),QString(),this,SLOT(browse()));
-        file->setToolTip(tr("Browse to a file"));
-        layout->addWidget( m_br,row,2 );
-        if (m==StringImage) 
+        m_brFile = m_br->addAction(QIcon(QString::fromLatin1(":/images/file.png")),QString(),this,SLOT(browseFile()));
+        m_brFile->setToolTip(tr("Browse to a file"));
+        if (m==StringImage)
         {
           m_im = new QLabel;
           m_im->setMinimumSize(1,55);
@@ -79,12 +81,13 @@ InputString::InputString( QGridLayout *layout,int &row,
           layout->addWidget( m_im,row,1 );
         }
       }
-      else 
+      if (m==StringDir || m==StringFileDir)
       {
-        QAction *dir = m_br->addAction(QIcon(QString::fromLatin1(":/images/folder.png")),QString(),this,SLOT(browse()));
-        dir->setToolTip(tr("Browse to a folder"));
-        layout->addWidget( m_br,row,2 );
+        m_brDir = m_br->addAction(QIcon(QString::fromLatin1(":/images/folder.png")),QString(),this,SLOT(browseDir()));
+        m_brDir->setToolTip(tr("Browse to a folder"));
       }
+      rowLayout->addWidget( m_br);
+      layout->addLayout( rowLayout, m==StringImage?row-1:row, 1, 1, 2 );
     }
     else
     {
@@ -96,9 +99,9 @@ InputString::InputString( QGridLayout *layout,int &row,
     row++;
   }
 
-  if (m_le)  connect( m_le,   SIGNAL(textChanged(const QString&)), 
+  if (m_le)  connect( m_le,   SIGNAL(textChanged(const QString&)),
                       this,   SLOT(setValue(const QString&)) );
-  if (m_com) connect( m_com,  SIGNAL(activated(const QString &)), 
+  if (m_com) connect( m_com,  SIGNAL(activated(const QString &)),
                       this,   SLOT(setValue(const QString &)) );
   m_str = s+QChar::fromLatin1('!'); // force update
   setValue(s);
@@ -146,7 +149,7 @@ void InputString::updateDefault()
       else
       {
         QFile Fout(m_str);
-        if(!Fout.exists()) 
+        if(!Fout.exists())
         {
           m_im->setText(tr("Sorry, cannot find file(")+m_str+QString::fromLatin1(");"));
         }
@@ -175,28 +178,30 @@ void InputString::setEnabled(bool state)
   if (m_le)  m_le->setEnabled(state);
   if (m_im)  m_im->setEnabled(state);
   if (m_br)  m_br->setEnabled(state);
+  if (m_brFile)  m_brFile->setEnabled(state);
+  if (m_brDir)  m_brDir->setEnabled(state);
   if (m_com) m_com->setEnabled(state);
   updateDefault();
 }
 
-void InputString::browse()
+void InputString::browseFile()
 {
   QString path = QFileInfo(MainWindow::instance().configFileName()).path();
-  if (m_sm==StringFile || m_sm==StringImage)
+  QString fileName = QFileDialog::getOpenFileName(&MainWindow::instance(),
+      tr("Select file"),path);
+  if (!fileName.isNull())
   {
-    QString fileName = QFileDialog::getOpenFileName(&MainWindow::instance(),
-        tr("Select file"),path);
-    if (!fileName.isNull()) 
+    QDir dir(path);
+    if (!MainWindow::instance().configFileName().isEmpty() && dir.exists())
     {
-      QDir dir(path);
-      if (!MainWindow::instance().configFileName().isEmpty() && dir.exists())
-      {
-        fileName = m_absPath ? fileName : dir.relativeFilePath(fileName);
-      }
-      setValue(fileName);
+      fileName = m_absPath ? fileName : dir.relativeFilePath(fileName);
     }
+    setValue(fileName);
   }
-  else // sm==StringDir
+}
+void InputString::browseDir()
+{
+  QString path = QFileInfo(MainWindow::instance().configFileName()).path();
   {
     QString dirName = QFileDialog::getExistingDirectory(&MainWindow::instance(),
         tr("Select directory"),path);
@@ -232,7 +237,7 @@ void InputString::setDefault()
   if (index!=-1 && m_com) m_com->setCurrentIndex(index);
 }
 
-QVariant &InputString::value() 
+QVariant &InputString::value()
 {
   return m_value;
 }
index 5bd76e2..4a873e0 100644 (file)
@@ -24,6 +24,7 @@ class QLineEdit;
 class QToolBar;
 class QComboBox;
 class QGridLayout;
+class QAction;
 
 class InputString : public QObject, public Input
 {
@@ -34,7 +35,8 @@ class InputString : public QObject, public Input
                       StringFile=1, 
                       StringDir=2, 
                       StringFixed=3,
-                      StringImage=4
+                      StringImage=4,
+                      StringFileDir=5
                     };
 
     InputString( QGridLayout *layout,int &row,
@@ -72,7 +74,8 @@ class InputString : public QObject, public Input
     void showHelp(Input *);
 
   private slots:
-    void browse();
+    void browseFile();
+    void browseDir();
     void clear();
     void help();
 
@@ -82,6 +85,8 @@ class InputString : public QObject, public Input
     QLineEdit    *m_le;
     QLabel       *m_im;
     QToolBar     *m_br;
+    QAction      *m_brFile;
+    QAction      *m_brDir;
     QComboBox    *m_com;
     QString       m_str;
     QString       m_default;
index 6be752f..a3bc524 100755 (executable)
@@ -64,7 +64,6 @@
 #define STR_PDF_HYPERLINKS        QString::fromLatin1("PDF_HYPERLINKS")
 #define STR_SEARCHENGINE          QString::fromLatin1("SEARCHENGINE")
 #define STR_HAVE_DOT              QString::fromLatin1("HAVE_DOT")
-#define STR_CLASS_DIAGRAMS        QString::fromLatin1("CLASS_DIAGRAMS")
 #define STR_CLASS_GRAPH           QString::fromLatin1("CLASS_GRAPH")
 #define STR_COLLABORATION_GRAPH   QString::fromLatin1("COLLABORATION_GRAPH")
 #define STR_GRAPHICAL_HIERARCHY   QString::fromLatin1("GRAPHICAL_HIERARCHY")
@@ -1132,19 +1131,26 @@ Step4::Step4(Wizard *wizard,const QHash<QString,Input*> &modelData)
   QGridLayout *gbox = new QGridLayout( this );
   gbox->addWidget(new QLabel(tr("Diagrams to generate")),0,0);
 
+  // CLASS_GRAPH = NO, HAVE_DOT = NO
   QRadioButton *rb = new QRadioButton(tr("No diagrams"));
   m_diagramModeGroup->addButton(rb, 0);
   gbox->addWidget(rb,1,0);
-  // CLASS_DIAGRAMS = NO, HAVE_DOT = NO
   rb->setChecked(true);
-  rb = new QRadioButton(tr("Use built-in class diagram generator"));
+
+  // CLASS_GRAPH = TEXT, HAVE_DOT = NO
+  rb = new QRadioButton(tr("Text only"));
   m_diagramModeGroup->addButton(rb, 1);
-  // CLASS_DIAGRAMS = YES, HAVE_DOT = NO
   gbox->addWidget(rb,2,0);
-  rb = new QRadioButton(tr("Use dot tool from the GraphViz package"));
+
+  // CLASS_GRAPH = YES/GRAPH, HAVE_DOT = NO
+  rb = new QRadioButton(tr("Use built-in class diagram generator"));
   m_diagramModeGroup->addButton(rb, 2);
   gbox->addWidget(rb,3,0);
-  // CLASS_DIAGRAMS = NO, HAVE_DOT = YES
+
+  // CLASS_GRAPH = YES/GRAPH, HAVE_DOT = YES
+  rb = new QRadioButton(tr("Use dot tool from the GraphViz package"));
+  m_diagramModeGroup->addButton(rb, 3);
+  gbox->addWidget(rb,4,0);
 
   m_dotGroup = new QGroupBox(tr("Dot graphs to generate"));
     QVBoxLayout *vbox = new QVBoxLayout;
@@ -1173,11 +1179,11 @@ Step4::Step4(Wizard *wizard,const QHash<QString,Input*> &modelData)
     m_dotGroup->setLayout(vbox);
     m_dotClass->setChecked(true);
     m_dotGroup->setEnabled(false);
-  gbox->addWidget(m_dotGroup,4,0);
+  gbox->addWidget(m_dotGroup,5,0);
 
   m_dotInclude->setChecked(true);
   m_dotCollaboration->setChecked(true);
-  gbox->setRowStretch(5,1);
+  gbox->setRowStretch(6,1);
 
   connect(m_diagramModeGroup,SIGNAL(buttonClicked(int)),
           this,SLOT(diagramModeChanged(int)));
@@ -1202,24 +1208,37 @@ void Step4::diagramModeChanged(int id)
   if (id==0) // no diagrams
   {
     updateBoolOption(m_modelData,STR_HAVE_DOT,false);
-    updateBoolOption(m_modelData,STR_CLASS_DIAGRAMS,false);
+    updateStringOption(m_modelData,STR_CLASS_GRAPH, QString::fromLatin1("NO"));
   }
-  else if (id==1) // builtin diagrams
+  else if (id==1) // text only
   {
     updateBoolOption(m_modelData,STR_HAVE_DOT,false);
-    updateBoolOption(m_modelData,STR_CLASS_DIAGRAMS,true);
+    updateStringOption(m_modelData,STR_CLASS_GRAPH, QString::fromLatin1("TEXT"));
   }
-  else if (id==2) // dot diagrams
+  else if (id==2) // builtin diagrams
+  {
+    updateBoolOption(m_modelData,STR_HAVE_DOT,false);
+    updateStringOption(m_modelData,STR_CLASS_GRAPH, QString::fromLatin1("YES"));
+  }
+  else if (id==3) // dot diagrams
   {
     updateBoolOption(m_modelData,STR_HAVE_DOT,true);
-    updateBoolOption(m_modelData,STR_CLASS_DIAGRAMS,false);
+    updateStringOption(m_modelData,STR_CLASS_GRAPH, QString::fromLatin1("YES"));
   }
-  m_dotGroup->setEnabled(id==2);
+  m_dotGroup->setEnabled(id==3);
 }
 
 void Step4::setClassGraphEnabled(int state)
 {
-  updateBoolOption(m_modelData,STR_CLASS_GRAPH,state==Qt::Checked);
+  QString classGraph = getStringOption(m_modelData,STR_CLASS_GRAPH);
+  if (state==Qt::Checked)
+  {
+    updateStringOption(m_modelData,STR_CLASS_GRAPH,QString::fromLatin1("YES"));
+  }
+  else if (classGraph==QString::fromLatin1("YES") || classGraph==QString::fromLatin1("GRAPH"))
+  {
+    updateStringOption(m_modelData,STR_CLASS_GRAPH,QString::fromLatin1("NO"));
+  }
 }
 
 void Step4::setCollaborationGraphEnabled(int state)
@@ -1255,22 +1274,21 @@ void Step4::setCallerGraphEnabled(int state)
 void Step4::init()
 {
   int id = 0;
-  if (getBoolOption(m_modelData,STR_HAVE_DOT))
+  QString classGraph = getStringOption(m_modelData,STR_CLASS_GRAPH).toLower();
+  if (classGraph==QString::fromLatin1("yes") || classGraph==QString::fromLatin1("graph"))
   {
-    m_diagramModeGroup->button(2)->setChecked(true); // Dot
-    id = 2;
+    id = getBoolOption(m_modelData,STR_HAVE_DOT) ? 3 : 2;
   }
-  else if (getBoolOption(m_modelData,STR_CLASS_DIAGRAMS))
+  else if (classGraph==QString::fromLatin1("text"))
   {
-    m_diagramModeGroup->button(1)->setChecked(true); // Builtin diagrams
     id = 1;
   }
   else
   {
-    m_diagramModeGroup->button(0)->setChecked(true); // no diagrams
     id = 0;
   }
-  m_dotGroup->setEnabled(id==2);
+  m_diagramModeGroup->button(id)->setChecked(true); // no diagrams
+  m_dotGroup->setEnabled(id==3);
   m_dotClass->setChecked(getBoolOption(m_modelData,STR_CLASS_GRAPH));
   m_dotCollaboration->setChecked(getBoolOption(m_modelData,STR_COLLABORATION_GRAPH));
   m_dotInheritance->setChecked(getBoolOption(m_modelData,STR_GRAPHICAL_HIERARCHY));
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/doc/._archoverview.eps b/doc/._archoverview.eps
new file mode 100644 (file)
index 0000000..60cfed6
Binary files /dev/null and b/doc/._archoverview.eps differ
diff --git a/doc/._infoflow.png b/doc/._infoflow.png
new file mode 100644 (file)
index 0000000..6c7f3e8
Binary files /dev/null and b/doc/._infoflow.png differ
index 9fc5e26..ec63ceb 100644 (file)
@@ -63,6 +63,7 @@ set(DOC_FILES
         expert_list_string.png
         expert_string_dir.png
         expert_string_file.png
+        expert_string_filedir.png
         expert_string_image.png
         expert_string_string.png
         external.doc
index 15d210e..40d9b85 100644 (file)
@@ -39,9 +39,9 @@ INPUT             = index.doc install.doc starting.doc docblocks.doc markdown.do
                     external.doc faq.doc trouble.doc features.doc \
                    doxygen_usage.doc doxywizard_usage.doc \
                    config.doc commands.doc htmlcmds.doc xmlcmds.doc emojisup.doc language.doc \
-                    perlmod.doc perlmod_tree.doc arch.doc changelog.doc
+                    perlmod.doc arch.doc changelog.doc
 FILE_PATTERNS     = *.cpp *.h *.doc
-EXAMPLE_PATH      = ../examples
+EXAMPLE_PATH      = ../examples .
 RECURSIVE         = NO
 TAGFILES          =
 ALLEXTERNALS      = NO
@@ -51,8 +51,8 @@ USE_PDFLATEX      = YES
 STRIP_CODE_COMMENTS = NO
 HTML_STYLESHEET   = doxygen_manual.css
 HTML_EXTRA_FILES  = doxygen_logo.svg
-ALIASES           = LaTeX="\f(\LaTeX\f)"
-ALIASES          += TeX="\f(\TeX\f)"
+ALIASES           = LaTeX="\f({\LaTeX}\f)"
+ALIASES          += TeX="\f({\TeX}\f)"
 ALIASES          += forceNewPage="\latexonly \newpage \endlatexonly"
 LATEX_BATCHMODE   = YES
 LATEX_EXTRA_STYLESHEET = manual.sty
index 31f5790..8e4b6c2 100644 (file)
@@ -1,6 +1,193 @@
 /** \page changelog Changelog
 \tableofcontents{html,latex}
 \section log_1_9 1.9 Series
+\subsection log_1_9_3 Release 1.9.3
+\htmlonly
+<b>(release date 31-12-2021)</b>
+</p>
+<h3>Bug fixes</h3>
+<ul>
+<li>bug 679192 Missing images from generated qhp file [<a href="https://github.com/doxygen/doxygen/commit/06e3488cf4d83ad834071d3129352273159f09ab">view</a>]</li>
+<li>bug_161451 @copydoc cannot span mutliple lines [<a href="https://github.com/doxygen/doxygen/commit/e508c16ba7ce0d151f22157013691fc290001e4c">view</a>]</li>
+<li>bug_365053 Wrong reference to ::classname [<a href="https://github.com/doxygen/doxygen/commit/04a13d3ad918efb533c67b80429e45550bf39c83">view</a>] and [<a href="https://github.com/doxygen/doxygen/commit/872421a090753577d8e5e783c7b0729024bc2251">view</a>]</li>
+<li>bug_411629 ifdef-ed namespaces generate &quot;endif&quot; namespace (C#) [<a href="https://github.com/doxygen/doxygen/commit/9fd98e8be4fc13fd816a32d9714afcdc363779d6">view</a>]</li>
+<li>bug_562008 cpp directives in \code fragments breaks subsequent links replacement [<a href="https://github.com/doxygen/doxygen/commit/cccdb5bb0cc3172dfb314ff0df5ce109fca64c31">view</a>]</li>
+<li>bug_683640 Docset info.plist file doesn&#39;t include feed URL [<a href="https://github.com/doxygen/doxygen/commit/4a6e0ac904b8269a78dea664b3d1d7d3afb1a016">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/af952099ffcd93c81d536aa1527c3b202872d276">view</a>]</li>
+<li>bug_684050 line continuation in (auto)linking [<a href="https://github.com/doxygen/doxygen/commit/9288bde048646e732de13526792c6ca789bb8837">view</a>]</li>
+<li>bug_688384 JavaDoc @link does not use code font [<a href="https://github.com/doxygen/doxygen/commit/22ada22cdfbbb7cca598b07b70c75643695be5ac">view</a>]</li>
+<li>bug_693776 @copydoc not working properly [<a href="https://github.com/doxygen/doxygen/commit/bc7201841e07328959770be0b3e07e42dd6f4e11">view</a>]</li>
+<li>bug_712290 A command that will generate a warning during compilation [<a href="https://github.com/doxygen/doxygen/commit/d7086493c64fed9f8a3f04a1fdec394594b42fec">view</a>]</li>
+<li>bug_722111 - &#39;function&#39; is displayed as C++ keyword (green) in HTML output [<a href="https://github.com/doxygen/doxygen/commit/538a72c3f88b53e7b8c0e284c559cb0019026f1a">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/e1502f6f7a8dc0186f7b1ab1363a601239d4e5fc">view</a>]</li>
+<li>bug_749992 XML output - &quot;bodyend&quot; inside location tag sometimes prints the wrong row. [<a href="https://github.com/doxygen/doxygen/commit/c9fdb6c1071b5c9f19fe74f9f5e92febffb56bd7">view</a>]</li>
+<li>bug_750666 Usergroup (layout.xml) url=&quot;[none]&quot; doesn&#39;t work [<a href="https://github.com/doxygen/doxygen/commit/92821c0186fbb8ba30d5d640203e03a9b6e22af5">view</a>]</li>
+<li>bug_753629 PLANTUML_JAR_PATH Environment Variable Needs Documenting [<a href="https://github.com/doxygen/doxygen/commit/50ebbf2bb3e2a9d3fad0849b394ad900d920e82c">view</a>]</li>
+<li>bug_766164 Class Members is missing in the CHM. [<a href="https://github.com/doxygen/doxygen/commit/f375348b61dbd31c1455f7e23d4300f99695e8d3">view</a>]</li>
+<li>bug_771606 &#39;doxygen -w&#39; should not require existence of header.html/footer.html even if listed in an options file [<a href="https://github.com/doxygen/doxygen/commit/3a9f46678ef91f6942f9c15259423675c766dcbb">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/75ee26dd41c6b8419719af92fe277b4bb4534f91">view</a>]</li>
+<li>bug_772405 *_AUTOBRIEF=YES gobbles end of paragraph from brief [<a href="https://github.com/doxygen/doxygen/commit/37c226f2fe01a249b15d55d3950191aca3f63ef2">view</a>]</li>
+<li>bug_774111 GENERATE_LEGEND with svg graphs [<a href="https://github.com/doxygen/doxygen/commit/0a2bb195d5883428df69fa1cf3dd6356908e4d1d">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/2c4743cc5f3c47a8136e5ec0f7985117b68b1cd3">view</a>]</li>
+<li>bug_774167  Left nav pane [<a href="https://github.com/doxygen/doxygen/commit/528523a6bd1c1619308882af7260296b44f8ffe1">view</a>]</li>
+<li>bug_791832 [<a href="https://github.com/doxygen/doxygen/commit/42912711ea3d7bb2fa0a7aa1871a13b2de2e9989">view</a>]</li>
+<li>bug_792690  Spaces MAKEINDEX_CMD_NAME don&#39;t work the same as other config options [<a href="https://github.com/doxygen/doxygen/commit/f5e6c90a978777e3426db7d8d894b26f50484580">view</a>]</li>
+<li>bug_796673 doxygen markdown engine disallow parentheses in image title [<a href="https://github.com/doxygen/doxygen/commit/cf2bf5c164f3f569fcf2682ff5ac077caa302093">view</a>]</li>
+<li>issue #7434 Error in LaTeX output of doxygen documentation of VHDL [<a href="https://github.com/doxygen/doxygen/commit/6743b2fd418b433fe3835900a95055e454468217">view</a>]</li>
+<li>issue #7687 Write directory dependency graphs recursively. [<a href="https://github.com/doxygen/doxygen/commit/6fee7e8650c8eec32990fbb714ddc43bf2aa6c34">view</a>]</li>
+<li>issue #7807 Incorrect handling of triple backticks with specifying language. [<a href="https://github.com/doxygen/doxygen/commit/48888bf7e47fa8fb3258aa38f0a558682858a396">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/a7d403098bddff8c0feca6c562ba05f03b5ab2ae">view</a>]</li>
+<li>issue #8528 Markdown links to Markdown pages with explicit page command are broken [<a href="https://github.com/doxygen/doxygen/commit/a36c9943ffe2e64954c1370a6bd9ce33aaf54cec">view</a>]</li>
+<li>issue #8590 XML: Issue with spacing around &lt;programlisting&gt; [<a href="https://github.com/doxygen/doxygen/commit/6c5b9295509e9cf189c91f9d1cabf41249dbd4bb">view</a>]</li>
+<li>issue #8724 @ingroup not working with concepts [<a href="https://github.com/doxygen/doxygen/commit/20fd82817cb91f9d8fdbfa5c636a176f17320b7d">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/93ab156f1ee4546396e04a3c7f4d13f74691fe8e">view</a>]</li>
+<li>issue #8726 Confused by C++20 trailing requires-clause [<a href="https://github.com/doxygen/doxygen/commit/4bf942faa3128099a4fbc47162e11b0545487fd5">view</a>]</li>
+<li>issue #8730 Read from invalid IncludeInfo object (version 1.9.2, Ubuntu 20.04) [<a href="https://github.com/doxygen/doxygen/commit/afd308219d0f0ac764fe56922c3f492a2772fa13">view</a>]</li>
+<li>issue #8734 @note with @parblock within a table data cell breaks the HTML output [<a href="https://github.com/doxygen/doxygen/commit/f3a396295800e17896bab0cf2c17b9d6d433c3b3">view</a>]</li>
+<li>issue #8738 Fixed sizes in project area of HTML output [<a href="https://github.com/doxygen/doxygen/commit/47dec8a1c3ed4468ec36be103bf0aa5d682c6040">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/815aebca80369b6ad9bcdfd075c72ab74c1f8f19">view</a>]</li>
+<li>issue #8743 &lt;tt&gt; missinterpreted [<a href="https://github.com/doxygen/doxygen/commit/0629f588a634b76e9fbad96e20d31d6900d26603">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/ec8f340cda0b391a14253cad202f40c7ffe4e1ca">view</a>]</li>
+<li>issue #8747 Improve output with WARN_AS_ERROR = FAIL_ON_WARNINGS [<a href="https://github.com/doxygen/doxygen/commit/174e23565a50b0b8dc333ff16a40de93b62793f1">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/bce44eef3037114760aa242362122b024536220d">view</a>]</li>
+<li>issue #8750 Crashes with 1.9.2 on Ubuntu 21.04 [<a href="https://github.com/doxygen/doxygen/commit/04d9e4c78389265a6e02e1c5fa221dab6eef81cf">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/1a2744d0cca9f5b1f2cfa749f6d004a376a6ee02">view</a>]</li>
+<li>issue #8752 Generated filenames depend on undefined behaviour - doxygen output not reproducible [<a href="https://github.com/doxygen/doxygen/commit/44e27fa3eac7658f93571a9b9556fd65400f85af">view</a>]</li>
+<li>issue #8753 qhp file corrupt when subsection with no parent section [<a href="https://github.com/doxygen/doxygen/commit/c6861973edb147d261ed9375a115a45ce81c4ea8">view</a>]</li>
+<li>issue #8755 :: lost in nested names when using markdown [<a href="https://github.com/doxygen/doxygen/commit/dd97018dca2f2c118cd0f813392ed81b1a98b2f4">view</a>]</li>
+<li>issue #8757 Segfault when using external search engine [<a href="https://github.com/doxygen/doxygen/commit/2b76fc789be10c82922bb687591ee39fda92e425">view</a>]</li>
+<li>issue #8767 Order of pages in the tree view changes from 1.9.1 to 1.9.2 [<a href="https://github.com/doxygen/doxygen/commit/8ee309708beb0a410e56fb4133849ed8197d3bcf">view</a>]</li>
+<li>issue #8785 Markdown runs on &lt;PRE&gt; if class attribute is specified [<a href="https://github.com/doxygen/doxygen/commit/29c0286f879812a08c7203d3d02fb039eea082b6">view</a>]</li>
+<li>issue #8789 qhp/qch broken in master [<a href="https://github.com/doxygen/doxygen/commit/89afdcc22e2f18962c067eb8e641506c826b5a9a">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/fed7b6ffb2f8007bd6155017f9edd7256f0940de">view</a>]</li>
+<li>issue #8802 Nested \cond sections are not started (#8804) [<a href="https://github.com/doxygen/doxygen/commit/ee8f3fb7a2ed74ee30ae3202707617e97f6641ff">view</a>]</li>
+<li>issue #8811 Incorrect xml tags in source code listing (XML output) [<a href="https://github.com/doxygen/doxygen/commit/1f2097e81af7d2b6f22863b3f3fafc792ff68629">view</a>]</li>
+<li>issue #8815 fix group close [<a href="https://github.com/doxygen/doxygen/commit/e0147ebc533ba75ad2fcd518a5be6ef8b174dacc">view</a>]</li>
+<li>issue #8817 If \if, \else or \endif is in a list, the subsequent list entry is not formatted as list entry but in &quot;raw format&quot; [<a href="https://github.com/doxygen/doxygen/commit/6f26d1fabb982ddecbf889dcaf7f358fb77305d1">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/8e57e86fc882c11cf040edd85fa36b3444136736">view</a>]</li>
+<li>issue #8838 export &quot;something&quot; { } wrong parsing [<a href="https://github.com/doxygen/doxygen/commit/1cf26658b7dc6c4e16acbcc2c912fea4acbd39c5">view</a>]</li>
+<li>issue #8851 Python call graph is not completely correct [<a href="https://github.com/doxygen/doxygen/commit/b614cedd61218caf9902ba6779871520ba102813">view</a>]</li>
+<li>issue #8853 LaTeX generated output fails to compile [<a href="https://github.com/doxygen/doxygen/commit/79ee7e60f69db208d6a22662adf752b24016351a">view</a>]</li>
+<li>issue #8854 Class hierarchy diagram is not correct, if inherited from Python built-in class ABC [<a href="https://github.com/doxygen/doxygen/commit/6e7c2861eeaad89c8c9b79241689a3ee3ede2f20">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/9ef185a76bd6e8fd40b2fe14405ae8c1ea500156">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/e9b2a97863881c6fce0836bb61863b1160178d57">view</a>]</li>
+<li>issue #8854 Class hierarchy diagram is not correct, if inherited from Python built-in class ABC [<a href="https://github.com/doxygen/doxygen/commit/be7752e5e273321089bac4f07f66d0305580f837">view</a>]</li>
+<li>issue #8855 Unable to build 1.9.2 [<a href="https://github.com/doxygen/doxygen/commit/5c3a4ad2773fc911b341b36b00528603afbe1602">view</a>]</li>
+<li>issue #8864 Markdown Tables cannot merge cells both horizontally and vertically [<a href="https://github.com/doxygen/doxygen/commit/ce5421c3709a7d225e964226ee178b24e251c130">view</a>]</li>
+<li>issue #8867 Fortran source file that contains the character literal &quot;import&quot; or &#39;import&#39; [<a href="https://github.com/doxygen/doxygen/commit/53ee06da134bce394f854ea691dd39e673ca0d29">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/ed749f55f4dbf9c911ddf585676f0f39e17f5b6f">view</a>]</li>
+<li>issue #8882 Java: Issue with virtual as identifier [<a href="https://github.com/doxygen/doxygen/commit/18c18e680f3938554ffeeedac029d10d3670f364">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/84e13392fb5a70d84ede80df65241963561d1933">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/da6dc3d35718d6d6c186540fb87ce4b2cdb6fb1c">view</a>]</li>
+<li>issue #8884 Java: Issue with dotted annotations [<a href="https://github.com/doxygen/doxygen/commit/fcf8823a132ed47c436acbe267fdc731df848b65">view</a>]</li>
+<li>issue #8889 &quot;.html_html&quot; attached to some url links when linking to external library [<a href="https://github.com/doxygen/doxygen/commit/f6c66d9e5d703733e5da7c4c0b15323bbe7eb722">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/fce99519dbc4571f5191fe61bcaeffbbce9a2949">view</a>]</li>
+<li>issue #8889 Extra &quot;.html&quot; attached to some url links when linking to external library [<a href="https://github.com/doxygen/doxygen/commit/4cca8d10c2fc18f390c8e4811535fae507dc7e8b">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/be62dae734e5c84e16959eb1aec0b1be9c241aa0">view</a>]</li>
+<li>issue #8895 [bisected]Directory dependency graph has stopped working [<a href="https://github.com/doxygen/doxygen/commit/bc9031924d0e8e8ae964ee7c5450be78b3abc3d5">view</a>]</li>
+<li>issue #8898 c#: Inherit documentation from interface property (not working as no docs displayed) [<a href="https://github.com/doxygen/doxygen/commit/fad9afdf78aedd968d8b8ebb00aae29e93a362ab">view</a>]</li>
+<li>issue #8903 Overload of function template can cause docs to be repeated [<a href="https://github.com/doxygen/doxygen/commit/566284bf3971c77283e02465129055a401a9f631">view</a>]</li>
+<li>issue #8905 Documentation: WARN_NO_PARAMDOC not disabled by EXTRACT_ALL? [<a href="https://github.com/doxygen/doxygen/commit/0377430a85d0fbced3092e3ddd52c8fe3dde47dd">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/137e97587926eef120009cc9008e37198ef76fc1">view</a>]</li>
+<li>issue #8909 Build error with git head GCC (version 12, Nov 2021) [<a href="https://github.com/doxygen/doxygen/commit/f0e049e546f15b3fcdae987b86858de409da5516">view</a>]</li>
+<li>issue #8911 Undocumented function with C++ requires clause [<a href="https://github.com/doxygen/doxygen/commit/e55dae5c9bca0a95934fe7c3c6dbba9c63142c92">view</a>]</li>
+<li>issue #8914 Double Square Bracket &acirc;&#128;&#147; somewhere &acirc;&#128;&#147; stop Doxygen [<a href="https://github.com/doxygen/doxygen/commit/78929f9919f134fc6d7cb2166ed8aab2cbf28588">view</a>]</li>
+<li>issue #8918 \emoji does not support emoji with ZWJ [<a href="https://github.com/doxygen/doxygen/commit/50e31fffcb3ccf9403a8c48b427d2876f137b23b">view</a>]</li>
+<li>issue #8921 Overloaded function (with templates as change) is not displayed in html page [<a href="https://github.com/doxygen/doxygen/commit/225160928d545c0768842558624aa654f6fab906">view</a>]</li>
+<li>issue #8924 Horizontal scroll bar missing in HTML for wide class=&quot;dotgraph&quot; objects [<a href="https://github.com/doxygen/doxygen/commit/590198b416cd53313d150428d2f912586065ea0d">view</a>]</li>
+<li>issue #8925 Java: Issue with enum parsing (xml output) [<a href="https://github.com/doxygen/doxygen/commit/4651b949112d5086dc12b403ac1d55d93406df1b">view</a>]</li>
+<li>issue #8932 XML output: table caption doesn&#39;t have ID [<a href="https://github.com/doxygen/doxygen/commit/58b39b6505012709786d998ac597775e0e63b2eb">view</a>]</li>
+<li>issue #8933 Return type &quot;unsigned int constexpr&quot; not parsed properly [<a href="https://github.com/doxygen/doxygen/commit/078a4bb89f3d995c802ab512bd7e03cd444793b5">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/fe6c5d3191d14a079e694333c3e55ce33ecc677e">view</a>]</li>
+<li>issue #8934 documentation &#39;DEP&#39; s.b. &#39;DEB&#39; [<a href="https://github.com/doxygen/doxygen/commit/2faa40f914b3070ba8ed7ed429af7781b5887103">view</a>]</li>
+<li>issue #8935 &#39;make docs&#39; fails when building PDF [<a href="https://github.com/doxygen/doxygen/commit/71bc09e2e47bab26619f0067133b7cf604ccd933">view</a>]</li>
+<li>issue #8940 Not parsing #if correctly in C++ [<a href="https://github.com/doxygen/doxygen/commit/aaa48c8a451951148750a11c7992c55c0a605fd6">view</a>]</li>
+<li>issue #8948 collaboration diagram should include smart pointer members [<a href="https://github.com/doxygen/doxygen/commit/5f3730769399fbbb82cbebb77e3b0bab3600095b">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/e64a05126d4393c111d9fb9872a76b33371272e8">view</a>]</li>
+<li>issue #8953 Improve markdown image handling [<a href="https://github.com/doxygen/doxygen/commit/5bb622158e33aac19d23068c08f434aaced60b4c">view</a>]</li>
+<li>issue #8956 Section links in markdown mainpage not working [<a href="https://github.com/doxygen/doxygen/commit/3a4db857340aeff18dcd57291e036809a0273449">view</a>]</li>
+<li>issue #8965 Allow other names for plantuml.jar [<a href="https://github.com/doxygen/doxygen/commit/9dd215f0404dfe4d8c869e95de904a37f1878b18">view</a>]</li>
+<li>issue #8973 Incorrect citations for entries with double dash and for cross references [<a href="https://github.com/doxygen/doxygen/commit/f03ccd841357324a4ab5440f055e405e671e6371">view</a>]</li>
+<li>issue #9857 C# incorrect interpretation of &#39;?&#39;-operators [<a href="https://github.com/doxygen/doxygen/commit/57b531137ad0a6106c77c2dc57c1249c6e3ad6b9">view</a>]</li>
+<li>Coloring of the nodes in the inheritance graph [<a href="https://github.com/doxygen/doxygen/commit/2ef002d0524ae060123eea88b225b83ac63addb7">view</a>]</li>
+<li>Fixed problem with large HTML tooltips running of the web page. [<a href="https://github.com/doxygen/doxygen/commit/a179fde5bf00f8639f7fe5f69ac13b7e70270818">view</a>]</li>
+<li>Coverity: logically dead code [<a href="https://github.com/doxygen/doxygen/commit/69b27d69a1bac6373e4ddada24c6459d6c5fc08a">view</a>]</li>
+<li>Coverity: uninitialized struct elements [<a href="https://github.com/doxygen/doxygen/commit/81156b309df9ea43fb0125d7d29d1a6582f20a04">view</a>]</li>
+<li>Coverity: side_effect_free: Calling countLines(yyscanner) is only useful for its return value, which is ignored. [<a href="https://github.com/doxygen/doxygen/commit/789969fd9a9f17e196551ce7664241b5bccb9a3c">view</a>]</li>
+<li>Using in/out in C# results in doubling it [<a href="https://github.com/doxygen/doxygen/commit/f35888a7807dbe85e24652466df1c45b7dcac846">view</a>]</li>
+<li>Restore default SIGINT handler inside the signal handler [<a href="https://github.com/doxygen/doxygen/commit/1ed1990afea03a32ba5ac078a931e15eb4853e27">view</a>]</li>
+<li>In HTML the @image title did not appear as tooltip and quotes were not properly escaped [<a href="https://github.com/doxygen/doxygen/commit/8df4e9faf24a9b93a047c90736a1cfc537f07c25">view</a>]</li>
+<li>Double member names in python source code [<a href="https://github.com/doxygen/doxygen/commit/dd2734aa4ce3339d461e93efcec635593554e387">view</a>]</li>
+<li>Fix memory corruption in TextStream. [<a href="https://github.com/doxygen/doxygen/commit/11bd374ea216b561deaf9be675ddd8941b80a487">view</a>]</li>
+<li>Handle decltype(*) return types in declinfo.l [<a href="https://github.com/doxygen/doxygen/commit/4146739ebdc656e4893a3cdc9106290164c3586d">view</a>]</li>
+<li>Warnings when using `CREATE_SUBDIRS` and `HTMLHELP` [<a href="https://github.com/doxygen/doxygen/commit/940a520be801d6445e94138e81880794493f4d11">view</a>]</li>
+<li>Don&#39;t use full path for *file in XML output [<a href="https://github.com/doxygen/doxygen/commit/dce954a21eeeda68c5a414630228909f39f99ea1">view</a>]</li>
+<li>Incorrect handling of JAVA style code statement in preprocessor [<a href="https://github.com/doxygen/doxygen/commit/0eafc2ec96d4c7b2f85ea9d5538a014d0650b0fa">view</a>]</li>
+<li>Incorrect linecount in case of JAVADOC_AUTOBRIEF set [<a href="https://github.com/doxygen/doxygen/commit/096aef20929d64cded0d630a2f5a2f56cc9eef32">view</a>]</li>
+<li>Incorrect markdown links. [<a href="https://github.com/doxygen/doxygen/commit/0fc914056407a94ced8a0f96cc887b8ec831c952">view</a>]</li>
+<li>Incorrect warning regarding SQLITE3 seyyttings [<a href="https://github.com/doxygen/doxygen/commit/fc0884a8bf4ef8701365b071520e302fdeea5829">view</a>]</li>
+<li>Incorrect warnings due to WARN_IF_DOC_ERROR=NO [<a href="https://github.com/doxygen/doxygen/commit/147d6ccb348c97999d99b39cfa370ec39e36ccd5">view</a>]</li>
+<li>Incorrect xml tags in source code listing (XML output) [<a href="https://github.com/doxygen/doxygen/commit/7714ad3a06e3a56e6d02887e94078d5887c904dc">view</a>]</li>
+<li>Doxygen stops on invalid namespace name [<a href="https://github.com/doxygen/doxygen/commit/56ceda853f55e040b74349fe7cdabd749ecd12fc">view</a>]</li>
+<li>Problems with blockquotes in markdown [<a href="https://github.com/doxygen/doxygen/commit/5f75ff14582400a77068df5ff0f4f0ec0693adee">view</a>]</li>
+<li>Fortran: Warning on empty \cond statement plus extra empty line. [<a href="https://github.com/doxygen/doxygen/commit/05150beee4bc74e185844e69a9c1c9e1af332817">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/f31a630b83ac6d8fedaaeeb72d4f8c49dd40ed78">view</a>]</li>
+<li>Escaped double quotes inside double quotes [<a href="https://github.com/doxygen/doxygen/commit/89774bd095476a2fbccab6d46514553bdb12a9ee">view</a>]</li>
+<li>Fixed problem where member attributes were not rendered properly [<a href="https://github.com/doxygen/doxygen/commit/e321a870fda2c1c5bf759d6320b0063675f79fcd">view</a>]</li>
+<li>Forward declaration of enum class. [<a href="https://github.com/doxygen/doxygen/commit/9d08517540ef0b765e3b8aebe5d3aba94ab99d29">view</a>]</li>
+<li>Handling \code in non doxygen comment [<a href="https://github.com/doxygen/doxygen/commit/5f7d123cda1a08deca58b313216848e0a710611d">view</a>]</li>
+<li>Warning with python file starting and ending with __ as file name [<a href="https://github.com/doxygen/doxygen/commit/4c627bc6f4fab5baafc01f7d14a4062e2ed79ec0">view</a>]</li>
+<li>Improve warning location for undocumented parameters/return types [<a href="https://github.com/doxygen/doxygen/commit/2b4e6885fde3776625339f17e24b27de0ecf7ce2">view</a>]</li>
+<li>Limit number of list levels in output [<a href="https://github.com/doxygen/doxygen/commit/c050f64978f734dd027d8d2099bacd81e0a749e3">view</a>]</li>
+<li>Unmatched tt tag. [<a href="https://github.com/doxygen/doxygen/commit/4193a8f950e6f21420be4783b540ed3cefca826b">view</a>]</li>
+<li>Value of first @copydoc could end up in the brief description. [<a href="https://github.com/doxygen/doxygen/commit/950c6ce0f3930bceb16da34cc9b366e64c5d791a">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/ab74ff26b0f9ba3f31d1dce605c4a1809ca9cb5c">view</a>]</li>
+</ul>
+<h3>Features</h3>
+<ul>
+<li>Write directory dependency graphs recursively. [<a href="https://github.com/doxygen/doxygen/commit/6d5a075dbbf622a10e5d6c24293306957838961b">view</a>]</li>
+<li>Added missing symbols needed to enable SANITIZE_UNDEFINED [<a href="https://github.com/doxygen/doxygen/commit/1bed57b942b306c67700828d74dafd4e07c510b1">view</a>]</li>
+<li>Add the xml output format to the image command as generic format [<a href="https://github.com/doxygen/doxygen/commit/c533e37efa7a859680e1c356006f1152d48eeba0">view</a>]</li>
+<li>Add the HTML and XML commands to the index [<a href="https://github.com/doxygen/doxygen/commit/a6ea781e7e70cce5802b768fddafc04c1f1959e1">view</a>]</li>
+<li>Added explanation for directory dependency graphs in graph manual. [<a href="https://github.com/doxygen/doxygen/commit/11aa05b27d26af4b04fe9c4d5e2b6694553b1f98">view</a>]</li>
+<li>Avoid tampering with special commands while doing markdown parsing [<a href="https://github.com/doxygen/doxygen/commit/511e7aee7e3fd13931dc71207b6c9769795d1bac">view</a>] and [<a href="https://github.com/doxygen/doxygen/commit/d7ce8d08175ab96b4b99025b7484fa9a16c78f57">view</a>]</li>
+<li>Adding HTML tag &lt;cite&gt; [<a href="https://github.com/doxygen/doxygen/commit/a55934e83f572aad1d01f21ac71c55f20142eaf7">view</a>]</li>
+<li>Adding engine to xml output for plantuml [<a href="https://github.com/doxygen/doxygen/commit/308acdbab2d794494011fe6d431959f797aaf3a0">view</a>]</li>
+<li>Czech localization update, added all missing czech localization strings up to 1.9.3 [<a href="https://github.com/doxygen/doxygen/commit/4aecec9b6d60c284b55475f9b43c03862e26e3e7">view</a>]</li>
+<li>translate chinese upto version 1.9.2 [<a href="https://github.com/doxygen/doxygen/commit/0da84b77dd9de829f78130fb81fd595cab00dab4">view</a>]</li>
+<li>Updated swedish translation to 1.9.2 [<a href="https://github.com/doxygen/doxygen/commit/e4d9f94c4b4f0c67041cea44acb6eb5aba0ba55f">view</a>]</li>
+<li>Greek translation updated to 1.9.2. [<a href="https://github.com/doxygen/doxygen/commit/231fc095a9d80ab1e56de453d08866db360bb4a9">view</a>]</li>
+<li>Portuguese translators upddated to 1.9.3. [<a href="https://github.com/doxygen/doxygen/commit/dfc5d3d7953efa317e81c00028181e5cb4871c0b">view</a>]</li>
+<li>UTF-8 characters in email address [<a href="https://github.com/doxygen/doxygen/commit/7e03841cc2f12e25e1b0810c48b132252560fadb">view</a>]</li>
+<li>Support for char32_t etc. in code coloring [<a href="https://github.com/doxygen/doxygen/commit/e5cb9a4536488589ac64186b0d82d0a2857bedc0">view</a>]</li>
+<li>Changed license of doxmlparser from GPLv2 to MIT [<a href="https://github.com/doxygen/doxygen/commit/c90ff8ccc6fc23658a4c4abd1123511074c37f47">view</a>]</li>
+<li>Better error message in case of a fatal error in a lexer [<a href="https://github.com/doxygen/doxygen/commit/a019b33403ae3325bd772780499e71bd31026316">view</a>]</li>
+<li>Better readable warnings / debug messages incase of warning with token / return value in docparser [<a href="https://github.com/doxygen/doxygen/commit/d64d39226f206f9f1f5f46927ca16047b45a5f81">view</a>]</li>
+<li>value attribute for &lt;li&gt; tag [<a href="https://github.com/doxygen/doxygen/commit/efe54bb64a9d9ddb06803a7b63f6ac873a68ee4e">view</a>] and [<a href="https://github.com/doxygen/doxygen/commit/79c56dd177f2c78afcbc1b8fb22002016492d18f">view</a>]</li>
+<li>Copy original dotfile to output directory in case of DOT_CLEANUP is not set [<a href="https://github.com/doxygen/doxygen/commit/21323cd16d56124744f6b37283991af466dafa22">view</a>]</li>
+<li>allow using percentual numbers for images dimensions [<a href="https://github.com/doxygen/doxygen/commit/8ac8aa4f4e77a8c73b7792436be5790f1c0d7eb4">view</a>]</li>
+<li>Make email obfuscation optional [<a href="https://github.com/doxygen/doxygen/commit/fe818b6cf945359c498dc7a25067788f9ae70a53">view</a>]</li>
+<li>Improvement of WARN_LOGFILE possibilities [<a href="https://github.com/doxygen/doxygen/commit/3ce0f7936765df68088c9ccd4322ed73699a8592">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/5040e822b54f74db78cad58f9ec5544c056860d6">view</a>]</li>
+<li>No warning in case non existing macro parameter [<a href="https://github.com/doxygen/doxygen/commit/a85b813acb2b05670fb40c81b32f03f2e4ecf219">view</a>]</li>
+<li>HTML tag details [<a href="https://github.com/doxygen/doxygen/commit/04d662959c02ee126f5bf251e2c2b29283395b71">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/d4debbbacbd617b90e64ed3c8d034e837b84ff05">view</a>]</li>
+<li>Include qualified names in `&lt;memberdef&gt;`s in XML output. [<a href="https://github.com/doxygen/doxygen/commit/3bbc10b026ae46dea24aa5714b863f9b6b0dee44">view</a>]</li>
+</ul>
+<h3>Deprecated functionality</h3>
+<ul>
+<li>CLASS_DIAGRAM has become obsolete.
+The same functionality can now be achieved using HAVE_DOT and CLASS_GRAPH. Old settings in the Doxyfile will be automatically converted when reading or updating it.
+[<a href="https://github.com/doxygen/doxygen/commit/3bd1926ec385c0ff604266ad5ae79096eeb4d991">view</a>], [<a href="https://github.com/doxygen/doxygen/commit/d653ee094138f745b32d938f93a5c4e93d400432">view</a>], and [<a href="https://github.com/doxygen/doxygen/commit/28f54bec358fe74d32cb1b71924f433ca68675e6">view</a>]</li>
+</ul>
+<h3>Refactoring and cleanup</h3>
+<ul>
+<li>Add support for optional ranges to reg::Ex and use it util.cpp [<a href="https://github.com/doxygen/doxygen/commit/fedfebdc12428fb0c0d03bb6333e2dfd9fbf3a31">view</a>]</li>
+<li>Allow using obsolete config values while upgrading [<a href="https://github.com/doxygen/doxygen/commit/9ff74182ee44409238308010110dc76f6f0a2c12">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/bc4502727df4e8bfe113590f42c3135516ebe913">view</a>]</li>
+<li>Use std::unordered_set for better performance [<a href="https://github.com/doxygen/doxygen/commit/6e7801b35ec33250ad154a7b9b468342b99719dc">view</a>]</li>
+<li>Refactoring: Use std::unique_ptr&lt;Private&gt; for PIMPL idiom instead of raw pointer [<a href="https://github.com/doxygen/doxygen/commit/fe10ed2c54ca16fb8f2bf3696d2c691ed77ab449">view</a>]</li>
+<li>Refactoring: changes how context data is cached. [<a href="https://github.com/doxygen/doxygen/commit/6ea18b2a34c9d960a303bcf645cc70f130666703">view</a>]</li>
+<li>Refactoring: fixed typo and improved code uniformity [<a href="https://github.com/doxygen/doxygen/commit/7ec63964bc8c377d34aacd2bce70d0a002db3f54">view</a>]</li>
+<li>Refactoring: replace custom reference counting by std::shared_ptr [<a href="https://github.com/doxygen/doxygen/commit/9d1588df26d9ec2a2d0e7b7987049b4714a021c6">view</a>]</li>
+<li>Refactoring: replace raw pointers with std::unique_ptr in template.cpp [<a href="https://github.com/doxygen/doxygen/commit/c9fc3ac4b9c83a9b0ed853b4508bc9f604ac7deb">view</a>]</li>
+<li>Refactoring: replace the last raw pointers by std::unique_ptr in template.cpp [<a href="https://github.com/doxygen/doxygen/commit/ca79354b6dad47570b5f9bfb540460fe11ce0402">view</a>]</li>
+<li>Refactoring: use fixed maps for properties [<a href="https://github.com/doxygen/doxygen/commit/c44fc0d96ffd4df1b813f46520f6c3fcfd2ae2c4">view</a>]</li>
+<li>Remove obsolete states from lexer code [<a href="https://github.com/doxygen/doxygen/commit/830ae9d970b88137c2c972de6c14bba940340254">view</a>]</li>
+<li>Remove redundant checks in config file [<a href="https://github.com/doxygen/doxygen/commit/1c85524ee79e08b987160c6b1da23f457f3c96ba">view</a>]</li>
+<li>Remove redundant range checks in config file [<a href="https://github.com/doxygen/doxygen/commit/f2640ec6f05b8334417f9ad1127d3183dedf2f9e">view</a>]</li>
+<li>Remove some implicit casts to improve portability of the code [<a href="https://github.com/doxygen/doxygen/commit/0d28550e0d4f51b7f6296818d72d5c30543874ba">view</a>]</li>
+<li>Remove unnecessary conversions for enum type options [<a href="https://github.com/doxygen/doxygen/commit/81adb94d1bcb794e23f9e1961c369f50604a0c54">view</a>]</li>
+<li>Optimize Markdown::isBlockCommand() [<a href="https://github.com/doxygen/doxygen/commit/2d1f4ed992ce4819d6e5710fa2fbbd20317bcf1e">view</a>]</li>
+<li>Moved util.h:escapePath() to QCString::quoted() [<a href="https://github.com/doxygen/doxygen/commit/4b89f13e93f32e616a64e8c167eea4a0963b5a1c">view</a>]</li>
+<li>layout.cpp and tagreader.cpp both defined class ElementCallbacks [<a href="https://github.com/doxygen/doxygen/commit/95875b1f9470656cbfb6ca4dcc5896b42c688429">view</a>]</li>
+<li>Removed global variables for RTF and Latex, and made some fixes [<a href="https://github.com/doxygen/doxygen/commit/1d0eb05e5a5e0a927de81854d9ef482102761a19">view</a>]</li>
+<li>Represent enum in the config file also as an enum in the code [<a href="https://github.com/doxygen/doxygen/commit/a0fb56e0560d657d6fde8ade9e74624c9412eb4d">view</a>]</li>
+<li>Make generateClassDocs() process files in parallel [<a href="https://github.com/doxygen/doxygen/commit/0599b1900c1eacb49d7d17a45e031e942838946d">view</a>]</li>
+<li>Make generateFileDocs() process files in parallel [<a href="https://github.com/doxygen/doxygen/commit/f74a0c5caf7be77c33721eb20dfcaef5f96eaf2e">view</a>]</li>
+<li>Name of used struct [<a href="https://github.com/doxygen/doxygen/commit/818f1f1171c2875db1c5f594c0359309573ebfa1">view</a>]</li>
+<li>Performance enhancements [<a href="https://github.com/doxygen/doxygen/commit/a5daaca66e2431001a94421101222ba2f6590f36">view</a>]</li>
+<li>Restructuring and fixes [<a href="https://github.com/doxygen/doxygen/commit/768a8f1baccff853d1c60967bf341f699d740f9b">view</a>]</li>
+<li>Better search criterion for RTF INCLUDETEXT [<a href="https://github.com/doxygen/doxygen/commit/896e2cf7c2cf471dcb297d43f3ef741c912ef74f">view</a>]</li>
+<li>Consistent messages regarding enabling settings [<a href="https://github.com/doxygen/doxygen/commit/143149410977da2872b5122e6d8aa8fb587eac94">view</a>]</li>
+<li>Improve type safety of scanner code by not using void* for yyscan_t [<a href="https://github.com/doxygen/doxygen/commit/04d51aece784edf0cdb87626de5a09bcd605f236">view</a>]</li>
+</ul>
+<p>
+\endhtmlonly
+
 \subsection log_1_9_2 Release 1.9.2
 \htmlonly
 <b>(release date 18-08-2021)</b>
index 1a9dc72..2c0686b 100644 (file)
@@ -169,6 +169,7 @@ documentation:
 \refitem cmdpublic \\public
 \refitem cmdpublicsection \\publicsection
 \refitem cmdpure \\pure
+\refitem cmdraisewarning \\raisewarning
 \refitem cmdref \\ref
 \refitem cmdrefitem \\refitem
 \refitem cmdrelated \\related
@@ -1443,6 +1444,34 @@ contains \c TEST, or \c DEV
   The command will most commonly be used in combination with \ref cfg_aliases "ALIASES"
   to ignore not supported commands that are present for e.g. other processing tools.
 <hr>
+\section cmdraisewarning \\raisewarning ( text to be shown as warning )
+
+  \addindex \\raisewarning
+  All the text, excluding the command, till the end of the line is is literally shown
+  as a documentation warning. The text, including the command, is removed from the output.
+  The command will most commonly be used in combination with \ref cfg_aliases "ALIASES"
+  to show a specific warning.
+  \par Example:
+\verbatim
+\raisewarning My specific warnning
+
+\warnNoDoc
+
+\warnNoDoc{My specific warnning}
+\endverbatim
+   together with:
+\verbatim
+ALIASES  = warnNoDoc="\raisewarning Missing documentation"
+ALIASES += warnNoDoc{1}="\raisewarning Incomplete documentation: \1"
+\endverbatim
+   will  result in:
+\verbatim
+   ex_1.md:1: warning: My specific warnning
+   ex_1.md:3: warning: Missing documentation
+   ex_1.md:5: warning: Incomplete documentation: My specific warnning
+\endverbatim
+
+<hr>
 \section cmdelse \\else
 
   \addindex \\else
@@ -2653,7 +2682,7 @@ Commands for visual enhancements
   ... the \a x and \a y coordinates are used to ...
 
   Equivalent to \ref cmde "\\e" and \ref cmdem "\\em".
-  To emphasize multiple words use \<em\>multiple words\</em\>.
+  To emphasize multiple words use \ref htmltag_EM "\<em\>"multiple words\ref htmltag_endEM "\</em\>".
 
 <hr>
 \section cmdarg \\arg { item-description }
@@ -2693,8 +2722,8 @@ Commands for visual enhancements
 
   \addindex \\b
   Displays the argument \<word\> using a bold font.
-  Equivalent to \<b\>word\</b\>.
-  To put multiple words in bold use \<b\>multiple words\</b\>.
+  Equivalent to \ref htmltag_B "\<b\>"word\ref htmltag_endB "\</b\>".
+  To put multiple words in bold use \ref htmltag_B "\<b\>"multiple words\ref htmltag_endB "\</b\>".
 
 <hr>
 \section cmdc \\c <word>
@@ -2702,7 +2731,7 @@ Commands for visual enhancements
   \addindex \\c
   Displays the argument \<word\> using a typewriter font.
   Use this to refer to a word of code.
-  Equivalent to \<tt\>word\</tt\>.
+  Equivalent to \ref htmltag_TT "\<tt\>"word\ref htmltag_endTT "\</tt\>".
 
   \par Example:
   Typing:
@@ -2713,7 +2742,7 @@ Commands for visual enhancements
      ... This function returns \c void and not \c int ...
 
   Equivalent to \ref cmdp "\\p"
-  To have multiple words in typewriter font use \<tt\>multiple words\</tt\>.
+  To have multiple words in typewriter font use \ref htmltag_TT "\<tt\>"multiple words\ref htmltag_endTT "\</tt\>".
 
 <hr>
 \section cmdcode \\code['{'<word>'}']
@@ -3152,7 +3181,7 @@ class Receiver
   ... this is a \e really good example ...
 
   Equivalent to \ref cmda "\\a" and \ref cmdem "\\em".
-  To emphasize multiple words use \<em\>multiple words\</em\>.
+  To emphasize multiple words use \ref htmltag_EM "\<em\>"multiple words\ref htmltag_endEM "\</em\>".
 
 <hr>
 \section cmdem \\em <word>
@@ -3170,7 +3199,7 @@ class Receiver
   ... this is a \em really good example ...
 
   Equivalent to \ref cmda "\\a" and \ref cmde "\\e".
-  To emphasize multiple words use \<em\>multiple words\</em\>.
+  To emphasize multiple words use \ref htmltag_EM "\<em\>"multiple words\ref htmltag_endEM "\</em\>".
 
 <hr>
 \section cmdendcode \\endcode
@@ -3356,7 +3385,7 @@ class Receiver
 
   The first argument specifies the output format in which the image should
   be embedded. Currently, the following values are supported:
-  \c html, \c latex, \c docbook and \c rtf.
+  \c html, \c latex, \c docbook, \c rtf and \c xml.
 
   The second argument specifies the file name of the image.
   doxygen will look for files in the paths (or files) that you specified
@@ -3493,7 +3522,7 @@ class Receiver
 \section cmdn \\n
 
   \addindex \\n
-  Forces a new line. Equivalent to \<br\> and inspired by
+  Forces a new line. Equivalent to \ref htmltag_BR "\<br\>" and inspired by
   the \c printf function.
 
 <hr>
@@ -3512,7 +3541,7 @@ class Receiver
   ... the \p x and \p y coordinates are used to ...
 
   Equivalent to \ref cmdc "\\c"
-  To have multiple words in typewriter font use \<tt\>multiple words\</tt\>.
+  To have multiple words in typewriter font use \ref htmltag_TT "\<tt\>"multiple words\ref htmltag_endTT "\</tt\>".
 
 <hr>
 \section cmdrtfonly \\rtfonly
index 55ddbdc..cf55104 100644 (file)
@@ -336,7 +336,7 @@ The class page has the following specific elements:
       this class.
 <dt>\c inheritancegraph
   <dd>Represents the inheritance relations for a class.
-      Note that the CLASS_DIAGRAM option determines
+      Note that the \ref cfg_class_graph "CLASS_GRAPH" option determines
       if the inheritance relation is a list of base and derived classes or
       a graph.
 <dt>\c collaborationgraph
index a0b4285..436c678 100644 (file)
       functions that the function is directly or indirectly called by
       (see also section \ref cmdcallergraph "\\callergraph" and
        section \ref cmdhidecallergraph "\\hidecallergraph").
+  <li>If \ref cfg_directory_graph "DIRECTORY_GRAPH" is set to `YES`, doxygen will 
+      generate graphs that show the directory dependencies for every directory.
+      The graph will show directories as boxes.
+      Subdirectories are shown nested into the box of its parent directory.
+      The depth of the graph is configured through
+      \ref cfg_dir_graph_max_depth "DIR_GRAPH_MAX_DEPTH".
+      Include dependencies between the directories are shown as arrows.
   </ul>
 
   Using a \ref customize "layout file" you can determine which of the
        of type C, where B is a subtype of C (e.g. `C` could be `B`, `B*`, `T<B>*`). 
   </ul>
 
+  The elements in the directory dependency graphs have the following meaning:
+  <ul>
+  <li> A box with a \b bold border indicates the directory that the 
+       directory dependency graph has been generated for.
+  <li> A box with a <b>red solid</b> border indicates a directory whose 
+       subdirectories are not shown in the graph ("truncated").
+       To configure the depth of subdirectories that are shown in the graph 
+       see \ref cfg_dir_graph_max_depth "DIR_GRAPH_MAX_DEPTH".
+  <li> A box with a <b>red dashed</b> border indicates a truncated
+       directory whose parent directories are not shown in the graph either.
+  <li> A box with a \b dashed border other than red indicates that not all 
+       but at least one subdirectory are shown.
+  <li> A box with a <b>light gray</b> border indicates a directory with both of 
+       the following two attributes: 
+      <ul>
+        <li> Its parent directory is not shown.
+        <li> At least one subdirectory is shown.
+      </ul>
+  <li> A box with <b>no background color</b> indicates a directory which is not 
+       a subdirectory of the origin's parent directories which are shown.
+       The origin is the directory for which the directory dependency graph is 
+       shown.
+  <li> An \b arrow between two boxes indicates an include dependency between
+       two directories.
+       The include dependency exists if a file in a directory includes a
+       file of another directory.
+       If a directory that is involved in an include dependency is not shown in 
+       the graph, the arrow is attached to the first parent directory that is 
+       shown.
+       This parent directory is shown as truncated (see above).
+  </ul>
+
 
 Here are a couple of header files that together show the various diagrams
 that doxygen can generate: 
index 01fd4bd..677d931 100644 (file)
@@ -459,7 +459,7 @@ the script can be found in the path set via \ref cfg_example_path "EXAMPLE_PATH"
 \subsection pythonblocks Comment blocks in Python
 
 For Python there is a standard way of documenting the code using
-so called documentation strings (<tt>"""</tt>). Such strings are stored in \c __doc__
+so called documentation strings (<tt>\"\"\"</tt>). Such strings are stored in \c __doc__
 and can be retrieved at runtime. Doxygen will extract such comments
 and assume they have to be represented in a preformatted way.
 
index 8378a5c..597e6fd 100644 (file)
Binary files a/doc/doxywizard_page4.png and b/doc/doxywizard_page4.png differ
index 8b9e428..654b149 100644 (file)
@@ -175,6 +175,9 @@ The representation of the input field depends on the type of the configuration o
     <br>and a folder looks like:<br>
     \image{inline} html expert_string_dir.png
     \image{inline} latex expert_string_dir.png width=11.0cm
+    <br>and in case both a file or a folder is allowed, the look is:<br>
+    \image{inline} html expert_string_filedir.png
+    \image{inline} latex expert_string_filedir.png width=11.0cm
     <br>In case a file represents an image, doxygen also tries to display the selected image.
     Then a typical field looks like:<br>
     \image{inline} html expert_string_image.png
index 2b8a16c..7d6d377 100644 (file)
@@ -60,6 +60,8 @@ def get_emojis():
     return json.loads(raw_data)
 
 def download_images(dir_name):
+    if not os.path.exists(dir_name):
+        os.makedirs(dir_name)
     json_data = get_emojis()
     num_items = len(json_data)
     cur_item=0
diff --git a/doc/expert_string_filedir.png b/doc/expert_string_filedir.png
new file mode 100644 (file)
index 0000000..1434f00
Binary files /dev/null and b/doc/expert_string_filedir.png differ
index 524233c..14d5fa4 100644 (file)
@@ -23,100 +23,104 @@ of a HTML tag are passed on to the HTML output only
 (the \c HREF and \c NAME attributes for the \c A tag are the only exception).
 
 <ul>
-<li><tt>\<A HREF="..."\></tt> Starts a hyperlink 
+<li><tt>\anchor htmltag_A_HREF \addindex "\<A HREF=\"...\"\>"\<A HREF="..."\></tt> Starts a hyperlink 
                        (if supported by the output format). 
-<li><tt>\<A ID="..."\></tt> Starts a named anchor 
+<li><tt>\anchor htmltag_A_ID \addindex "\<A ID=\"...\"\>"\<A ID="..."\></tt> Starts a named anchor 
                        (if supported by the output format).
-<li><tt>\<A NAME="..."\></tt> Starts a named anchor 
+<li><tt>\anchor htmltag_A_NAME \addindex "\<A NAME=\"...\"\>"\<A NAME="..."\></tt> Starts a named anchor 
                        (if supported by the output format).
-<li><tt>\</A\></tt>    Ends a link or anchor 
-<li><tt>\<B\></tt>     Starts a piece of text displayed in a bold font.
-<li><tt>\</B\></tt>    Ends a <tt>\<B\></tt> section.
-<li><tt>\<BLOCKQUOTE\></tt> Starts a quotation block.
-<li><tt>\</BLOCKQUOTE\></tt> Ends the quotation block.
-<li><tt>\<BR\></tt>    Forces a line break.
-<li><tt>\<CENTER\></tt> starts a section of centered text.
-<li><tt>\</CENTER\></tt> ends a section of centered text.
-<li><tt>\<CAPTION\></tt> Starts a caption. Use within a table only.
-<li><tt>\</CAPTION\></tt> Ends a caption. Use within a table only.
-<li><tt>\<CODE\></tt>  Starts a piece of text displayed in a typewriter font.
+<li><tt>\anchor htmltag_endA \addindex "\</A\>"\</A\></tt>    Ends a link or anchor 
+<li><tt>\anchor htmltag_B \addindex "\<B\>"\<B\></tt>     Starts a piece of text displayed in a bold font.
+<li><tt>\anchor htmltag_endB \addindex "\</B\>"\</B\></tt>    Ends a \ref htmltag_B "\<B\>" section.
+<li><tt>\anchor htmltag_BLOCKQUOTE \addindex "\<BLOCKQUOTE\>"\<BLOCKQUOTE\></tt> Starts a quotation block.
+<li><tt>\anchor htmltag_endBLOCKQUOTE \addindex "\</BLOCKQUOTE\>"\</BLOCKQUOTE\></tt> Ends the quotation block.
+<li><tt>\anchor htmltag_BR \addindex "\<BR\>"\<BR\></tt>    Forces a line break.
+<li><tt>\anchor htmltag_CENTER \addindex "\<CENTER\>"\<CENTER\></tt> starts a section of centered text.
+<li><tt>\anchor htmltag_endCENTER \addindex "\</CENTER\>"\</CENTER\></tt> ends a section of centered text.
+<li><tt>\anchor htmltag_CAPTION \addindex "\<CAPTION\>"\<CAPTION\></tt> Starts a caption. Use within a table only.
+<li><tt>\anchor htmltag_endCAPTION \addindex "\</CAPTION\>"\</CAPTION\></tt> Ends a caption. Use within a table only.
+<li><tt>\anchor htmltag_CITE \addindex "\<CITE\>"\<CITE\></tt> Starts a section of text displayed in a font specific for citations.
+<li><tt>\anchor htmltag_endCITE \addindex "\</CITE\>"\</CITE\></tt> Ends a \ref htmltag_CITE "\<CITE\>" section.
+<li><tt>\anchor htmltag_CODE \addindex "\<CODE\>"\<CODE\></tt>  Starts a piece of text displayed in a typewriter font.
                        Note that only for C# code, this command is equivalent to 
-                       \ref cmdcode "\\code". 
-<li><tt>\</CODE\></tt> Ends a <tt>\<CODE\></tt> section.
+                       \ref cmdcode "\\code" (see \ref xmltag_code "\<code\>")
+<li><tt>\anchor htmltag_endCODE \addindex "\</CODE\>"\</CODE\></tt> Ends a \ref htmltag_CODE "\<CODE\>" section.
                        Note that only for C# code, this command is equivalent to
-                       \ref cmdendcode "\\endcode".
-<li><tt>\<DD\></tt>    Starts an item description.
-<li><tt>\</DD\></tt>   Ends an item description.
-<li><tt>\<DEL\></tt>   Starts a section of deleted text, typically shown strike through text.
-<li><tt>\</DEL\></tt>  Ends a section of deleted text.
-<li><tt>\<DFN\></tt>   Starts a piece of text displayed in a typewriter font.
-<li><tt>\</DFN\></tt>  Ends a <tt>\<DFN\></tt> section.
-<li><tt>\<DIV></tt>    Starts a section with a specific style (HTML only)
-<li><tt>\</DIV></tt>   Ends a section with a specific style (HTML only)
-<li><tt>\<DL\></tt>    Starts a description list.
-<li><tt>\</DL\></tt>   Ends a description list.
-<li><tt>\<DT\></tt>    Starts an item title.
-<li><tt>\</DT\></tt>   Ends an item title.
-<li><tt>\<EM\></tt>    Starts a piece of text displayed in an italic font.
-<li><tt>\</EM\></tt>   Ends a <tt>\<EM\></tt> section.
-<li><tt>\<HR\></tt>    Writes a horizontal ruler.
-<li><tt>\<H1\></tt>    Starts an unnumbered section.
-<li><tt>\</H1\></tt>   Ends an unnumbered section.
-<li><tt>\<H2\></tt>    Starts an unnumbered subsection.
-<li><tt>\</H2\></tt>   Ends an unnumbered subsection.
-<li><tt>\<H3\></tt>    Starts an unnumbered subsubsection.
-<li><tt>\</H3\></tt>   Ends an unnumbered subsubsection.
-<li><tt>\<H4\></tt>    Starts an unnumbered subsubsection.
-<li><tt>\</H4\></tt>   Ends an unnumbered subsubsection.
-<li><tt>\<H5\></tt>    Starts an unnumbered subsubsection.
-<li><tt>\</H5\></tt>   Ends an unnumbered subsubsection.
-<li><tt>\<H6\></tt>    Starts an unnumbered subsubsection.
-<li><tt>\</H6\></tt>   Ends an unnumbered subsubsection.
-<li><tt>\<I\></tt>     Starts a piece of text displayed in an italic font.
-<li><tt>\</I\></tt>    Ends a <tt>\<I\></tt> section.
-<li><tt>\<IMG SRC="..." ...\></tt>   This command is written with its attributes to the HTML output only. The SRC attribute is mandatory.
-<li><tt>\<INS\></tt>   Starts a section of inserted text, typically shown as underlined text.
-<li><tt>\</INS\></tt>  Ends a section of inserted text.
-<li><tt>\<LI\></tt>    Starts a new list item.
-<li><tt>\</LI\></tt>   Ends a list item.
-<li><tt>\<OL\></tt>    Starts a numbered item list.
-<li><tt>\</OL\></tt>   Ends a numbered item list.
-<li><tt>\<P\></tt>     Starts a new paragraph.
-<li><tt>\</P\></tt>    Ends a paragraph.
-<li><tt>\<PRE\></tt>   Starts a preformatted fragment.
-<li><tt>\</PRE\></tt>  Ends a preformatted fragment.
-<li><tt>\<SMALL\></tt> Starts a section of text displayed in a smaller font.
-<li><tt>\</SMALL\></tt> Ends a <tt>\<SMALL\></tt> section.
-<li><tt>\<SPAN></tt>   Starts an inline text fragment with a specific style (HTML only)
-<li><tt>\</SPAN></tt>  Ends an inline text fragment with a specific style (HTML only)
-<li><tt>\<S\></tt>     Starts a section of strike through text.
-<li><tt>\</S\></tt>    Ends a section of strike through text.
-<li><tt>\<STRIKE\></tt> Starts a section of strike through text.
-<li><tt>\</STRIKE\></tt> Ends a section of strike through text.
-<li><tt>\<STRONG\></tt> Starts a section of bold text.
-<li><tt>\</STRONG\></tt> Ends a section of bold text.
-<li><tt>\<SUB\></tt>   Starts a piece of text displayed in subscript.
-<li><tt>\</SUB\></tt>  Ends a <tt>\<SUB\></tt> section.
-<li><tt>\<SUP\></tt>   Starts a piece of text displayed in superscript.
-<li><tt>\</SUP\></tt>  Ends a <tt>\<SUP\></tt> section.
-<li><tt>\<TABLE\></tt> starts a table.
-<li><tt>\</TABLE\></tt> ends a table.
-<li><tt>\<TD\></tt>    Starts a new table data element.
-<li><tt>\</TD\></tt>   Ends a table data element.
-<li><tt>\<TH\></tt>    Starts a new table header.
-<li><tt>\</TH\></tt>   Ends a table header.
-<li><tt>\<TR\></tt>    Starts a new table row.
-<li><tt>\</TR\></tt>   Ends a table row.
-<li><tt>\<TT\></tt>    Starts a piece of text displayed in a typewriter font.
-<li><tt>\</TT\></tt>   Ends a <tt>\<TT\></tt> section.
-<li><tt>\<KBD\></tt>   Starts a piece of text displayed in a typewriter font.
-<li><tt>\</KBD\></tt>  Ends a <tt>\<KBD\></tt> section.
-<li><tt>\<U\></tt> Starts a section of underlined text.
-<li><tt>\</U\></tt> Ends a section of underlined text.
-<li><tt>\<UL\></tt>    Starts an unnumbered item list.
-<li><tt>\</UL\></tt>   Ends an unnumbered item list.
-<li><tt>\<VAR\></tt>   Starts a piece of text displayed in an italic font.
-<li><tt>\</VAR\></tt>  Ends a <tt>\<VAR\></tt> section.
+                       \ref cmdendcode "\\endcode" (see \ref xmltag_code "\<code\>").
+<li><tt>\anchor htmltag_DD \addindex "\<DD\>"\<DD\></tt>    Starts an item description.
+<li><tt>\anchor htmltag_endDD \addindex "\</DD\>"\</DD\></tt>   Ends an item description.
+<li><tt>\anchor htmltag_DEL \addindex "\<DEL\>"\<DEL\></tt>   Starts a section of deleted text, typically shown strike through text.
+<li><tt>\anchor htmltag_endDEL \addindex "\</DEL\>"\</DEL\></tt>  Ends a section of deleted text.
+<li><tt>\anchor htmltag_DETAILS \addindex "\<DETAILS\>"\<DETAILS\></tt> Starts a section of detailed text that the user can open and close (in HTML output))
+<li><tt>\anchor htmltag_endDETAILS \addindex "\</DETAILS\>"\</DETAILS\></tt> Ends a section of detailed text.
+<li><tt>\anchor htmltag_DFN \addindex "\<DFN\>"\<DFN\></tt>   Starts a piece of text displayed in a typewriter font.
+<li><tt>\anchor htmltag_endDFN \addindex "\</DFN\>"\</DFN\></tt>  Ends a \ref htmltag_DFN "\<DFN\>" section.
+<li><tt>\anchor htmltag_DIV \addindex "\<DIV\>"\<DIV></tt>    Starts a section with a specific style (HTML only)
+<li><tt>\anchor htmltag_endDIV \addindex "\</DIV\>"\</DIV></tt>   Ends a section with a specific style (HTML only)
+<li><tt>\anchor htmltag_DL \addindex "\<DL\>"\<DL\></tt>    Starts a description list.
+<li><tt>\anchor htmltag_endDL \addindex "\</DL\>"\</DL\></tt>   Ends a description list.
+<li><tt>\anchor htmltag_DT \addindex "\<DT\>"\<DT\></tt>    Starts an item title.
+<li><tt>\anchor htmltag_endDT \addindex "\</DT\>"\</DT\></tt>   Ends an item title.
+<li><tt>\anchor htmltag_EM \addindex "\<EM\>"\<EM\></tt>    Starts a piece of text displayed in an italic font.
+<li><tt>\anchor htmltag_endEM \addindex "\</EM\>"\</EM\></tt>   Ends a \ref htmltag_EM "\<EM\>" section.
+<li><tt>\anchor htmltag_HR \addindex "\<HR\>"\<HR\></tt>    Writes a horizontal ruler.
+<li><tt>\anchor htmltag_H1 \addindex "\<H1\>"\<H1\></tt>    Starts an unnumbered section.
+<li><tt>\anchor htmltag_endH1 \addindex "\</H1\>"\</H1\></tt>   Ends an unnumbered section.
+<li><tt>\anchor htmltag_H2 \addindex "\<H2\>"\<H2\></tt>    Starts an unnumbered subsection.
+<li><tt>\anchor htmltag_endH2 \addindex "\</H2\>"\</H2\></tt>   Ends an unnumbered subsection.
+<li><tt>\anchor htmltag_H3 \addindex "\<H3\>"\<H3\></tt>    Starts an unnumbered subsubsection.
+<li><tt>\anchor htmltag_endH3 \addindex "\</H3\>"\</H3\></tt>   Ends an unnumbered subsubsection.
+<li><tt>\anchor htmltag_H4 \addindex "\<H4\>"\<H4\></tt>    Starts an unnumbered subsubsection.
+<li><tt>\anchor htmltag_endH4 \addindex "\</H4\>"\</H4\></tt>   Ends an unnumbered subsubsection.
+<li><tt>\anchor htmltag_H5 \addindex "\<H5\>"\<H5\></tt>    Starts an unnumbered subsubsection.
+<li><tt>\anchor htmltag_endH5 \addindex "\</H5\>"\</H5\></tt>   Ends an unnumbered subsubsection.
+<li><tt>\anchor htmltag_H6 \addindex "\<H6\>"\<H6\></tt>    Starts an unnumbered subsubsection.
+<li><tt>\anchor htmltag_endH6 \addindex "\</H6\>"\</H6\></tt>   Ends an unnumbered subsubsection.
+<li><tt>\anchor htmltag_I \addindex "\<I\>"\<I\></tt>     Starts a piece of text displayed in an italic font.
+<li><tt>\anchor htmltag_endI \addindex "\</I\>"\</I\></tt>    Ends a \ref htmltag_I "\<I\>" section.
+<li><tt>\anchor htmltag_IMG \addindex "\<IMG SRC=\"...\"\>"\<IMG SRC="..." ...\></tt>   This command is written with its attributes to the HTML output only. The SRC attribute is mandatory.
+<li><tt>\anchor htmltag_INS \addindex "\<INS\>"\<INS\></tt>   Starts a section of inserted text, typically shown as underlined text.
+<li><tt>\anchor htmltag_endINS \addindex "\</INS\>"\</INS\></tt>  Ends a section of inserted text.
+<li><tt>\anchor htmltag_LI \addindex "\<LI\>"\<LI\></tt>    Starts a new list item.
+<li><tt>\anchor htmltag_endLI \addindex "\</LI\>"\</LI\></tt>   Ends a list item.
+<li><tt>\anchor htmltag_OL \addindex "\<OL\>"\<OL\></tt>    Starts a numbered item list.
+<li><tt>\anchor htmltag_endOL \addindex "\</OL\>"\</OL\></tt>   Ends a numbered item list.
+<li><tt>\anchor htmltag_P \addindex "\<P\>"\<P\></tt>     Starts a new paragraph.
+<li><tt>\anchor htmltag_endP \addindex "\</P\>"\</P\></tt>    Ends a paragraph.
+<li><tt>\anchor htmltag_PRE \addindex "\<PRE\>"\<PRE\></tt>   Starts a preformatted fragment.
+<li><tt>\anchor htmltag_endPRE \addindex "\</PRE\>"\</PRE\></tt>  Ends a preformatted fragment.
+<li><tt>\anchor htmltag_SMALL \addindex "\<SMALL\>"\<SMALL\></tt> Starts a section of text displayed in a smaller font.
+<li><tt>\anchor htmltag_endSMALL \addindex "\</SMALL\>"\</SMALL\></tt> Ends a \ref htmltag_SMALL "\<SMALL\>" section.
+<li><tt>\anchor htmltag_SPAN \addindex "\<SPAN\>"\<SPAN></tt>   Starts an inline text fragment with a specific style (HTML only)
+<li><tt>\anchor htmltag_endSPAN \addindex "\</SPAN\>"\</SPAN></tt>  Ends an inline text fragment with a specific style (HTML only)
+<li><tt>\anchor htmltag_S \addindex "\<S\>"\<S\></tt>     Starts a section of strike through text.
+<li><tt>\anchor htmltag_endS \addindex "\</S\>"\</S\></tt>    Ends a section of strike through text.
+<li><tt>\anchor htmltag_STRIKE \addindex "\<STRIKE\>"\<STRIKE\></tt> Starts a section of strike through text.
+<li><tt>\anchor htmltag_endSTRIKE \addindex "\</STRIKE\>"\</STRIKE\></tt> Ends a section of strike through text.
+<li><tt>\anchor htmltag_STRONG \addindex "\<STRONG\>"\<STRONG\></tt> Starts a section of bold text.
+<li><tt>\anchor htmltag_endSTRONG \addindex "\</STRONG\>"\</STRONG\></tt> Ends a section of bold text.
+<li><tt>\anchor htmltag_SUB \addindex "\<SUB\>"\<SUB\></tt>   Starts a piece of text displayed in subscript.
+<li><tt>\anchor htmltag_endSUB \addindex "\</SUB\>"\</SUB\></tt>  Ends a \ref htmltag_SUB "\<SUB\>" section.
+<li><tt>\anchor htmltag_SUP \addindex "\<SUP\>"\<SUP\></tt>   Starts a piece of text displayed in superscript.
+<li><tt>\anchor htmltag_endSUP \addindex "\</SUP\>"\</SUP\></tt>  Ends a \ref htmltag_SUP "\<SUP\>" section.
+<li><tt>\anchor htmltag_TABLE \addindex "\<TABLE\>"\<TABLE\></tt> starts a table.
+<li><tt>\anchor htmltag_endTABLE \addindex "\</TABLE\>"\</TABLE\></tt> ends a table.
+<li><tt>\anchor htmltag_TD \addindex "\<TD\>"\<TD\></tt>    Starts a new table data element.
+<li><tt>\anchor htmltag_endTD \addindex "\</TD\>"\</TD\></tt>   Ends a table data element.
+<li><tt>\anchor htmltag_TH \addindex "\<TH\>"\<TH\></tt>    Starts a new table header.
+<li><tt>\anchor htmltag_endTH \addindex "\</TH\>"\</TH\></tt>   Ends a table header.
+<li><tt>\anchor htmltag_TR \addindex "\<TR\>"\<TR\></tt>    Starts a new table row.
+<li><tt>\anchor htmltag_endTR \addindex "\</TR\>"\</TR\></tt>   Ends a table row.
+<li><tt>\anchor htmltag_TT \addindex "\<TT\>"\<TT\></tt>    Starts a piece of text displayed in a typewriter font.
+<li><tt>\anchor htmltag_endTT \addindex "\</TT\>"\</TT\></tt>   Ends a \ref htmltag_TT "\<TT\>" section.
+<li><tt>\anchor htmltag_KBD \addindex "\<KBD\>"\<KBD\></tt>   Starts a piece of text displayed in a typewriter font.
+<li><tt>\anchor htmltag_endKBD \addindex "\</KBD\>"\</KBD\></tt>  Ends a \ref htmltag_KBD "\<KBD\>" section.
+<li><tt>\anchor htmltag_U \addindex "\<U\>"\<U\></tt> Starts a section of underlined text.
+<li><tt>\anchor htmltag_endU \addindex "\</U\>"\</U\></tt> Ends a section of underlined text.
+<li><tt>\anchor htmltag_UL \addindex "\<UL\>"\<UL\></tt>    Starts an unnumbered item list.
+<li><tt>\anchor htmltag_endUL \addindex "\</UL\>"\</UL\></tt>   Ends an unnumbered item list.
+<li><tt>\anchor htmltag_VAR \addindex "\<VAR\>"\<VAR\></tt>   Starts a piece of text displayed in an italic font.
+<li><tt>\anchor htmltag_endVAR \addindex "\</VAR\>"\</VAR\></tt>  Ends a \ref htmltag_VAR "\<VAR\>" section.
 </ul>
 
 The special HTML4 character entities.<br>
index 53c4466..b1954d0 100644 (file)
@@ -155,7 +155,7 @@ To change this just edit the Makefile.
 the coreutils package). Other install tools may put the binaries in
 the wrong directory!
 
-If you have a RPM or DEP package, then please follow the
+If you have a RPM or DEB package, then please follow the
 standard installation procedure that is required for these packages.
 
 \section install_src_windows Compiling from source on Windows
index 12f3911..23c89a3 100644 (file)
@@ -45,6 +45,6 @@
   \markright{\thesection\ #1}%
 }
 %
-\usepackage{xpatch}
+\usepackage{regexpatch}
 \xpatchcmd{\part}{plain}{empty}{}{}
 
index 3904eb9..da52a88 100644 (file)
@@ -227,6 +227,16 @@ In addition doxygen provides a similar way to link a documented entity:
 
     [The link text](@ref MyClass)
 
+in case the first non whitespace character of the reference is a \c # this
+is interpreted as a doxygen link and replaced as a \ref cmdref "\@ref" command:
+
+    [The link text](#MyClass)
+
+will be interpreted as:
+
+    @ref MyClass "The link text"
+
+
 \subsubsection md_reflinks Reference Links
 
 Instead of putting the URL inline, you can also define the link separately
@@ -466,12 +476,33 @@ To link to a section in the same comment block you can use
 
     [Link text](#labelid)
 
-to link to a section in general, doxygen allows you to use \@ref
+to link to a section in general, doxygen allows you to use \ref cmdref "\@ref"
 
     [Link text](@ref labelid)
 
 Note this only works for the headers of level 1 to 4.
 
+\subsection md_image_attributes Image Attributes
+
+Standard Markdown has no support for controlling image dimensions
+which results in less flexibility when writing docs.
+
+PHP Markdown Extra allows you to add extra attributes to an
+image as in:
+
+    ![Caption text](/path/to/img.jpg){attributes}
+
+To allow for output format specific attributes the following syntax is supported
+
+    ![Caption text](/path/to/img.jpg){format: attributes, format: attributes}
+
+For a description of the possibilities see the paragraph
+\ref image_sizeindicator "Size indication" for the \ref cmdimage "\\image" command.
+
+For example:
+
+    ![Doxygen Logo](https://www.doxygen.org/images/doxygen.png){html: width=50%, latex: width=5cm}
+
 \section markdown_dox Doxygen specifics
 
 Even though doxygen tries to following the Markdown standard as closely as
@@ -706,7 +737,7 @@ new lines are allowed.
 Also for links there are limits; the link text, and link title each can
 contain only one new line, the URL may not contain any newlines.
 
-\section markdown_debug Debugging of problems
+\section markdown_debug Debugging problems
 
 When doxygen parses the source code it first extracts the comments blocks,
 then passes these through the Markdown preprocessor. The output of the
index 1ef4bbc..dcb9176 100644 (file)
@@ -79,7 +79,7 @@ to automate the use of these files are also added to
 <ul>
 
 <li>`doxylatex.pl`: This Perl script uses `DoxyDocs.pm` and 
-DoxyModel.pm to generate `doxydocs.tex`, a \TeX file containing 
+`DoxyModel.pm` to generate `doxydocs.tex`, a \TeX file containing 
 the documentation in a format that can be accessed by \LaTeX code. This 
 file is not directly LaTeXable.
 
@@ -192,9 +192,11 @@ you can look at the Perl scripts generated by doxygen (such as
 `doxylatex.pl` or `doxytemplate-latex.pl`) to get an idea on
 how to use `DoxyModel.pm`.
 
+\section perlmod_tree Perl Module Tree Nodes
+\includedoc perlmod_tree.doc
 
 \htmlonly
-Go to the <a href="perlmod_tree.html">next</a> section or return to the
+Go to the <a href="arch.html">next</a> section or return to the
  <a href="index.html">index</a>.
 \endhtmlonly
 
index a936320..b17224f 100644 (file)
@@ -1,7 +1,5 @@
-/*! \page perlmod_tree Perl Module Tree Nodes
-
-<h2>Nodes in the documentation tree of the Perl Module output
-format.</h2>
+<h3>Nodes in the documentation tree of the Perl Module output
+format.</h3>
 
 This is a description of the structure of the documentation tree in
 <b>DoxyDocs.pm</b>.  Each item in the list below describes a node in
@@ -373,11 +371,3 @@ The meaning of each node in the documentation tree is as follows:
 </ul>
 </ul>
 </ul>
-
-
-\htmlonly
-Go to the <a href="arch.html">next</a> section or return to the
- <a href="index.html">index</a>.
-\endhtmlonly
-
-*/
index 34aa3ed..4c2fce4 100644 (file)
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
- * 
+ *
  *
  * 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 
+ * 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.
  *
@@ -19,8 +19,8 @@
 Source files that are used as input to doxygen can be parsed by doxygen's
 built-in C-preprocessor.
 
-By default doxygen does only partial preprocessing. That is, it 
-evaluates conditional compilation statements (like \c \#if) and 
+By default doxygen does only partial preprocessing. That is, it
+evaluates conditional compilation statements (like \c \#if) and
 evaluates macro definitions, but it does not perform macro expansion.
 
 So if you have the following code fragment
@@ -44,8 +44,8 @@ Then by default doxygen will feed the following to its parser:
   static CONST_STRING version = "2.xx";
 \endverbatim
 
-You can disable all preprocessing by setting 
-\ref cfg_enable_preprocessing "ENABLE_PREPROCESSING" to \c 
+You can disable all preprocessing by setting
+\ref cfg_enable_preprocessing "ENABLE_PREPROCESSING" to \c
 NO in the configuration file. In the case above doxygen will then read
 both statements, i.e.:
 
@@ -55,7 +55,7 @@ both statements, i.e.:
 \endverbatim
 
 In case you want to expand the \c CONST_STRING macro, you should set the
-\ref cfg_macro_expansion "MACRO_EXPANSION" tag in the configuration file 
+\ref cfg_macro_expansion "MACRO_EXPANSION" tag in the configuration file
 to \c YES. Then the result after preprocessing becomes:
 
 \verbatim
@@ -65,18 +65,18 @@ to \c YES. Then the result after preprocessing becomes:
   static const char * version = "2.xx";
 \endverbatim
 
-Note that doxygen will now expand \e all macro definitions 
-(recursively if needed). This is often too much. Therefore, doxygen also 
-allows you to expand only those defines that you explicitly 
-specify. For this you have to set the 
+Note that doxygen will now expand \e all macro definitions
+(recursively if needed). This is often too much. Therefore, doxygen also
+allows you to expand only those defines that you explicitly
+specify. For this you have to set the
 \ref cfg_expand_only_predef "EXPAND_ONLY_PREDEF" tag to \c YES
-and specify the macro definitions after 
-the \ref cfg_predefined "PREDEFINED" or 
-\ref cfg_expand_as_defined "EXPAND_AS_DEFINED" tag.  
+and specify the macro definitions after
+the \ref cfg_predefined "PREDEFINED" or
+\ref cfg_expand_as_defined "EXPAND_AS_DEFINED" tag.
 
 A typically example where some help from the preprocessor is needed is
 when dealing with the language extension from Microsoft: \c __declspec. The same goes
-for GNU's \c \__attribute__ extension. Here is an example function.
+for GNU's \c __attribute__ extension. Here is an example function.
 
 \verbatim
 extern "C" void __declspec(dllexport) ErrorMsg( String aMessage,...);
@@ -86,7 +86,7 @@ When nothing is done, doxygen will be confused and see \c __declspec as
 some sort of function. To help doxygen one typically uses the following
 preprocessor settings:
 
-\verbatim  
+\verbatim
 ENABLE_PREPROCESSING   = YES
 MACRO_EXPANSION        = YES
 EXPAND_ONLY_PREDEF     = YES
@@ -96,16 +96,16 @@ PREDEFINED             = __declspec(x)=
 This will make sure the \c __declspec(dllexport) is removed before doxygen
 parses the source code.
 
-Similar settings can be used for removing \c \__attribute__ expressions from the input:
+Similar settings can be used for removing \c __attribute__ expressions from the input:
 
-\verbatim  
+\verbatim
 ENABLE_PREPROCESSING   = YES
 MACRO_EXPANSION        = YES
 EXPAND_ONLY_PREDEF     = YES
 PREDEFINED             = __attribute__(x)=
 \endverbatim
 
-For a more complex example, suppose you have the following obfuscated 
+For a more complex example, suppose you have the following obfuscated
 code fragment of an abstract base class called \c IUnknown:
 
 \verbatim
@@ -126,8 +126,8 @@ DECLARE_INTERFACE(IUnknown)
 };
 \endverbatim
 
-without macro expansion doxygen will get confused, but we may not want to 
-expand the \c REFIID macro, because it is documented and the user that reads 
+without macro expansion doxygen will get confused, but we may not want to
+expand the \c REFIID macro, because it is documented and the user that reads
 the documentation should use it when implementing the interface.
 
 By setting the following in the configuration file:
@@ -158,20 +158,20 @@ class  IUnknown
 };
 \endverbatim
 
-Note that the \ref cfg_predefined "PREDEFINED" tag accepts function 
+Note that the \ref cfg_predefined "PREDEFINED" tag accepts function
 like macro definitions
-(like \c DECLARE_INTERFACE ), normal macro 
-substitutions (like \c PURE and \c THIS) and plain 
+(like \c DECLARE_INTERFACE ), normal macro
+substitutions (like \c PURE and \c THIS) and plain
 defines (like \c __cplusplus).
 
-Note also that preprocessor definitions that are normally defined 
-automatically by the preprocessor (like \c __cplusplus), have to be defined 
+Note also that preprocessor definitions that are normally defined
+automatically by the preprocessor (like \c __cplusplus), have to be defined
 by hand with doxygen's parser (this is done because these defines
 are often platform/compiler specific).
 
-In some cases you may want to substitute a macro name or function by 
+In some cases you may want to substitute a macro name or function by
 something else without exposing the result to further macro substitution.
-You can do this but using the <code>:=</code> operator instead of 
+You can do this but using the <code>:=</code> operator instead of
 <code>=</code>
 
 As an example suppose we have the following piece of code:
@@ -188,8 +188,8 @@ for class \c QList is to define:
 PREDEFINED = QListT:=QList
 \endverbatim
 
-Here is an example provided by Valter Minute and Reyes Ponce that helps 
-doxygen to wade through the boilerplate code in Microsoft's ATL \& MFC 
+Here is an example provided by Valter Minute and Reyes Ponce that helps
+doxygen to wade through the boilerplate code in Microsoft's ATL \& MFC
 libraries:
 
 \verbatim
@@ -251,7 +251,7 @@ PREDEFINED           = "DECLARE_INTERFACE(name)=class name" \
 \endverbatim
 
 As you can see doxygen's preprocessor is quite powerful, but if you want
-even more flexibility you can always write an input filter and specify it 
+even more flexibility you can always write an input filter and specify it
 after the \ref cfg_input_filter "INPUT_FILTER" tag.
 
 If you are unsure what the effect of doxygen's preprocessing will be
@@ -264,8 +264,8 @@ or when the line numbers are not wanted:
   doxygen -d Preprocessor -d NoLineno
 \endverbatim
 This will instruct doxygen to dump the input sources to standard output after
-preprocessing has been done (Hint: set <code>QUIET = YES</code> and 
-<code>WARNINGS = NO</code> in the configuration file to disable any other 
+preprocessing has been done (Hint: set <code>QUIET = YES</code> and
+<code>WARNINGS = NO</code> in the configuration file to disable any other
 output).
 
 Note preprocessing is not done for all languages. Preprocessing is enabled for files
index a2e9be6..59ead57 100644 (file)
@@ -34,7 +34,7 @@
     or unions with the same name in your code. It should not crash however,
     rather it should ignore all of the classes with the same name except one.
 <li>Some commands do not work inside the arguments of other commands.
-    Inside a HTML link (i.e. \<a&nbsp;href="..."\>...\</a\>) for instance 
+    Inside a HTML link (i.e. \ref htmltag_A_HREF "\<A HREF=\"...\"\>"...\ref htmltag_endA "\</A\>") for instance 
     other commands (including other HTML commands) do not work!
     The sectioning commands are an important exception. 
 <li>Redundant braces can confuse doxygen in some cases. 
@@ -97,9 +97,11 @@ through the database if the same bug has already been submitted by others.
 If you believe you have found a new bug, 
 please <a href="https://github.com/doxygen/doxygen/issues/new">report it</a>.
 
-If you are unsure whether or not something is a bug, please ask help
-on the <a href="http://sourceforge.net/mail/?group_id=5971">users mailing list</a> 
-first (subscription is required).
+If you are unsure whether or not something is a bug, please ask help first
+(subscription is required)
+on the <a href="http://sourceforge.net/mail/?group_id=5971">users mailing list</a> or
+at <a href="https://stackoverflow.com/questions/tagged/doxygen">Stack Overflow</a>
+using the `doxygen` label.
 
 If you send only a (vague) description of a bug, you are usually not very 
 helpful and it will cost me much more time to figure out what you mean. 
index 6cb78bd..de9bfeb 100644 (file)
@@ -25,52 +25,57 @@ not very precise and a number of the examples given are of poor quality.
 Here is the list of tags supported by doxygen:
 
 <ul>
-<li><tt>\<c\></tt>     Identifies inline text that should be rendered as a 
+<li><tt>\anchor xmltag_c \addindex "\<c\>" \<c\></tt>     Identifies inline text that should be rendered as a 
                        piece of code. Similar to using <tt>\<tt\></tt>text<tt>\</tt\></tt>.
-<li><tt>\<code\></tt>  Set one or more lines of source code or program output.
+<li><tt>\anchor xmltag_code \addindex "\<code\>" <code\></tt>  Set one or more lines of source code or program output.
                        Note that this command behaves like \ref cmdcode "\\code" ... \ref cmdendcode "\\endcode"
                        for C# code, but it behaves like the HTML equivalent
-                       <tt>\<code\>...\</code\></tt> for other languages.
-<li><tt>\<description\></tt> Part of a <tt>\<list\></tt> command, describes an item.
-<li><tt>\<example\></tt> Marks a block of text as an example, ignored by doxygen.
-<li><tt>\<exception cref="member"\></tt> Identifies the exception a 
+                       \ref htmltag_CODE "\<CODE\>"...\ref htmltag_endCODE "\</CODE\>" for other languages.
+<li><tt>\anchor xmltag_description \addindex "\<description\>" \<description\></tt> Part of a \ref xmltag_list "\<list\>" command, describes an item.
+<li><tt>\anchor xmltag_example \addindex "\<example\>" \<example\></tt> Marks a block of text as an example, ignored by doxygen.
+<li><tt>\anchor xmltag_exception \addindex "\<exception\>" \<exception cref="member"\></tt> Identifies the exception a 
                          method can throw.
-<li><tt>\<include\></tt> Can be used to import a piece of XML from an external
+<li><tt>\anchor xmltag_include \addindex "\<include\>" \<include\></tt> Can be used to import a piece of XML from an external
                          file. Ignored by doxygen at the moment.
-<li><tt>\<inheritdoc\></tt> Can be used to insert the documentation of a 
+<li><tt>\anchor xmltag_inheritdoc \addindex "\<inheritdoc\>" \<inheritdoc\></tt> Can be used to insert the documentation of a 
                          member of a base class into the documentation of a 
                          member of a derived class that reimplements it.
-<li><tt>\<item\></tt> List item. Can only be used inside a <tt>\<list\></tt> context.
-<li><tt>\<list type="type"\></tt> Starts a list, supported types are <tt>bullet</tt>
+<li><tt>\anchor xmltag_item \addindex "\<item\>" \<item\></tt> List item. Can only be used inside a \ref xmltag_list "\<list\>" context.
+
+<li><tt>\anchor xmltag_list \addindex "\<list\>" \<list type="type"\></tt> Starts a list, supported types are <tt>bullet</tt>
                          or <tt>number</tt> and <tt>table</tt>. 
                          A list consists of a number of <tt>\<item\></tt> tags.
                          A list of type table, is a two column table which can have
                          a header.
-<li><tt>\<listheader\></tt>   Starts the header of a list of type "table".
-<li><tt>\<para\></tt>    Identifies a paragraph of text.
-<li><tt>\<param name="paramName"\></tt> Marks a piece of text as the documentation
+<li><tt>\anchor xmltag_listheader \addindex "\<listheader\>" \<listheader\></tt>   Starts the header of a list of type "table".
+<li><tt>\anchor xmltag_para \addindex "\<para\>" \<para\></tt>    Identifies a paragraph of text.
+<li><tt>\anchor xmltag_param \addindex "\<param\>" \<param name="paramName"\></tt> Marks a piece of text as the documentation
                          for parameter "paramName". Similar to 
                          using \ref cmdparam "\\param".
-<li><tt>\<paramref name="paramName"\></tt> Refers to a parameter with name
+<li><tt>\anchor xmltag_paramref \addindex "\<paramref\>" \<paramref name="paramName"\></tt> Refers to a parameter with name
                          "paramName". Similar to using \ref cmda "\\a".
-<li><tt>\<permission\></tt> Identifies the security accessibility of a member.
+<li><tt>\anchor xmltag_permission \addindex "\<permission\>" \<permission\></tt> Identifies the security accessibility of a member.
                          Ignored by doxygen.
-<li><tt>\<remarks\></tt> Identifies the detailed description. 
-<li><tt>\<returns\></tt> Marks a piece of text as the return value of a
+<li><tt>\anchor xmltag_remarks \addindex "\<remarks\>" \<remarks\></tt> Identifies the detailed description. 
+<li><tt>\anchor xmltag_returns \addindex "\<returns\>" \<returns\></tt> Marks a piece of text as the return value of a
                          function or method. Similar to using \ref cmdreturn "\\return".
-<li><tt>\<see cref="member"\></tt> Refers to a member. Similar to \ref cmdref "\\ref".
-<li><tt>\<seealso cref="member"\></tt> Starts a "See also" section referring
+<li><tt>\anchor xmltag_see \addindex "\<see\>" \<see cref="member"\></tt> Refers to a member. Similar to \ref cmdref "\\ref".
+<li><tt>\anchor xmltag_seealso \addindex "\<seealso\>" \<seealso cref="member"\></tt> Starts a "See also" section referring
                          to "member". Similar to using \ref cmdsa "\\sa" member.
-<li><tt>\<summary\></tt> Identifies the brief description.
+<li><tt>\anchor xmltag_summary \addindex "\<summary\>" \<summary\></tt> 
+                         In case this tag is used outside a \ref htmltag_DETAILS "\<DETAILS\>" tag this tag
+                         identifies the brief description.
                          Similar to using \ref cmdbrief "\\brief".
-<li><tt>\<term\></tt>    Part of a <tt>\<list\></tt> command.
-<li><tt>\<typeparam name="paramName"\></tt> Marks a piece of text as the documentation
+                         In case this tag is used inside a \ref htmltag_DETAILS "\<DETAILS\>" tag this tag
+                         identifies the heading of the \ref htmltag_DETAILS "\<DETAILS\>" tag.
+<li><tt>\anchor xmltag_term \addindex "\<term\>" \<term\></tt>    Part of a \ref xmltag_list "\<list\>" command.
+<li><tt>\anchor xmltag_typeparam \addindex "\<typeparam\>" \<typeparam name="paramName"\></tt> Marks a piece of text as the documentation
                          for type parameter "paramName". Similar to 
                          using \ref cmdparam "\\param".
-<li><tt>\<typeparamref name="paramName"\></tt> Refers to a parameter with name
+<li>\anchor xmltag_typeparamref \addindex "\<typeparamref\>"<tt>\<typeparamref name="paramName"\></tt> Refers to a parameter with name
                          "paramName". Similar to using \ref cmda "\\a".
-<li><tt>\<value\></tt>   Identifies a property. Ignored by doxygen.
-<li><tt>\<![CDATA[...]]\></tt> The text inside this tag (on the ...) is  handled as normal
+<li><tt>\anchor xmltag_value \addindex "\<value\>" \<value\></tt>   Identifies a property. Ignored by doxygen.
+<li><tt>\anchor xmltag_CDATA \addindex "\<![CDATA[...]]\>" \<![CDATA[...]]\></tt> The text inside this tag (on the ...) is  handled as normal
                          doxygen comment except for the XML special characters `<`, `>` and
                          `&` that are used as if they were escaped.
 </ul>
index e281abe..ff726b3 100644 (file)
@@ -544,7 +544,7 @@ static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigne
 
   if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/
   tree->numcodes = (unsigned)numcodes; /*number of symbols*/
-  uivector_resize(&tree->lengths, 0);
+  if (!uivector_resize(&tree->lengths, 0)) return 9955;
   if(!uivector_resizev(&tree->lengths, tree->numcodes, 0)) return 9905;
 
   if(numpresent == 0) /*there are no symbols at all, in that case add one symbol of value 0 to the tree (see RFC 1951 section 3.2.7) */
index 0a23900..34cf4d8 100644 (file)
@@ -16,7 +16,7 @@ foreach(lex_file ${LEX_FILES})
     FLEX_TARGET(${lex_file}        ${lex_file}.l        ${GENERATED_SRC}/${lex_file}.cpp        COMPILE_FLAGS "${LEX_FLAGS}")
 endforeach()
 
-add_library(mscgen
+add_library(mscgen STATIC
 gd.c
 gd_security.c
 gdfontt.c
index 96c5653..596ed90 100644 (file)
@@ -11,7 +11,7 @@ set_source_files_properties(${GENERATED_SRC}/xml.l.h PROPERTIES GENERATED 1)
 
 FLEX_TARGET(xml xml.l ${GENERATED_SRC}/xml.cpp COMPILE_FLAGS "${LEX_FLAGS}")
 
-add_library(xml
+add_library(xml STATIC
 ${GENERATED_SRC}/xml.cpp
 ${GENERATED_SRC}/xml.l.h
 )
index 1840648..0e0c5f7 100644 (file)
@@ -215,6 +215,7 @@ add_library(doxymain STATIC
     ${GENERATED_SRC}/ce_parse.cpp
     # custom generated files
     ${GENERATED_SRC}/lang_cfg.h
+    ${GENERATED_SRC}/configvalues.h
     ${GENERATED_SRC}/ce_parse.h
     ${GENERATED_SRC}/resources.cpp
     #
index 79b45da..ce7c2e1 100644 (file)
@@ -304,7 +304,7 @@ void CitationManager::generatePage()
       if      (line.find("<!-- BEGIN BIBLIOGRAPHY")!=-1) insideBib=TRUE;
       else if (line.find("<!-- END BIBLIOGRAPH")!=-1)    insideBib=FALSE;
       // determine text to use at the location of the @cite command
-      if (insideBib && (i=line.find("name=\"CITEREF_"))!=-1)
+      if (insideBib && ((i=line.find("name=\"CITEREF_"))!=-1 || (i=line.find("name=\"#CITEREF_"))!=-1))
       {
         int j=line.find("\">[");
         int k=line.find("]</a>");
@@ -315,7 +315,6 @@ void CitationManager::generatePage()
           uint uk=(uint)k;
           QCString label = line.mid(ui+14,uj-ui-14);
           QCString number = line.mid(uj+2,uk-uj-1);
-          label = substitute(substitute(label,"&ndash;","--"),"&mdash;","---");
           line = line.left(ui+14) + label + line.right(line.length()-uj);
           auto it = p->entries.find(label.str());
           //printf("label='%s' number='%s' => %p\n",qPrint(label),qPrint(number),it->second.get());
index 5de9907..42a0bc9 100644 (file)
@@ -486,7 +486,7 @@ std::string ClangTUParser::lookup(uint line,const char *symbol)
 }
 
 
-void ClangTUParser::writeLineNumber(CodeOutputInterface &ol,const FileDef *fd,uint line)
+void ClangTUParser::writeLineNumber(CodeOutputInterface &ol,const FileDef *fd,uint line,bool writeLineAnchor)
 {
   const Definition *d = fd ? fd->getSourceDefinition(line) : 0;
   if (d && d->isLinkable())
@@ -505,7 +505,7 @@ void ClangTUParser::writeLineNumber(CodeOutputInterface &ol,const FileDef *fd,ui
       ol.writeLineNumber(md->getReference(),
                          md->getOutputFileBase(),
                          md->anchor(),
-                         line);
+                         line,writeLineAnchor);
     }
     else // link to compound
     {
@@ -513,12 +513,12 @@ void ClangTUParser::writeLineNumber(CodeOutputInterface &ol,const FileDef *fd,ui
       ol.writeLineNumber(d->getReference(),
                          d->getOutputFileBase(),
                          d->anchor(),
-                         line);
+                         line,writeLineAnchor);
     }
   }
   else // no link
   {
-    ol.writeLineNumber(QCString(),QCString(),QCString(),line);
+    ol.writeLineNumber(QCString(),QCString(),QCString(),line,writeLineAnchor);
   }
 
   // set search page target
@@ -538,6 +538,7 @@ void ClangTUParser::codifyLines(CodeOutputInterface &ol,const FileDef *fd,const
   if (fontClass) ol.startFontClass(fontClass);
   const char *p=text,*sp=p;
   char c;
+  bool inlineCodeFragment = false;
   bool done=FALSE;
   while (!done)
   {
@@ -556,7 +557,7 @@ void ClangTUParser::codifyLines(CodeOutputInterface &ol,const FileDef *fd,const
       if (fontClass) ol.endFontClass();
       ol.endCodeLine();
       ol.startCodeLine(TRUE);
-      writeLineNumber(ol,fd,line);
+      writeLineNumber(ol,fd,line,inlineCodeFragment);
       if (fontClass) ol.startFontClass(fontClass);
     }
     else
@@ -583,6 +584,7 @@ void ClangTUParser::writeMultiLineCodeLink(CodeOutputInterface &ol,
   {
    tooltip = d->briefDescriptionAsTooltip();
   }
+  bool inlineCodeFragment = false;
   bool done=FALSE;
   char *p=(char *)text;
   while (!done)
@@ -598,7 +600,7 @@ void ClangTUParser::writeMultiLineCodeLink(CodeOutputInterface &ol,
       ol.writeCodeLink(d->codeSymbolType(),ref,file,anchor,sp,tooltip);
       ol.endCodeLine();
       ol.startCodeLine(TRUE);
-      writeLineNumber(ol,fd,line);
+      writeLineNumber(ol,fd,line,inlineCodeFragment);
     }
     else
     {
@@ -760,8 +762,9 @@ void ClangTUParser::writeSources(CodeOutputInterface &ol,const FileDef *fd)
 
   unsigned int line=1,column=1;
   QCString lineNumber,lineAnchor;
+  bool inlineCodeFragment = false;
   ol.startCodeLine(TRUE);
-  writeLineNumber(ol,fd,line);
+  writeLineNumber(ol,fd,line,inlineCodeFragment);
   for (unsigned int i=0;i<p->numTokens;i++)
   {
     CXSourceLocation start = clang_getTokenLocation(p->tu, p->tokens[i]);
@@ -773,7 +776,7 @@ void ClangTUParser::writeSources(CodeOutputInterface &ol,const FileDef *fd)
       line++;
       ol.endCodeLine();
       ol.startCodeLine(TRUE);
-      writeLineNumber(ol,fd,line);
+      writeLineNumber(ol,fd,line,inlineCodeFragment);
     }
     while (column<c) { ol.codify(" "); column++; }
     CXString tokenString = clang_getTokenSpelling(p->tu, p->tokens[i]);
@@ -906,6 +909,10 @@ std::unique_ptr<ClangTUParser> ClangParser::createTUParser(const FileDef *fd) co
 //--------------------------------------------------------------------------
 #else // use stubbed functionality in case libclang support is disabled.
 
+class ClangTUParser::Private
+{
+};
+
 void ClangTUParser::switchToFile(const FileDef *fd)
 {
 }
@@ -914,6 +921,14 @@ void ClangTUParser::parse()
 {
 }
 
+ClangTUParser::ClangTUParser(const ClangParser &,const FileDef *) : p(std::make_unique<Private>())
+{
+}
+
+ClangTUParser::~ClangTUParser()
+{
+}
+
 std::string ClangTUParser::lookup(uint,const char *)
 {
   return std::string();
index 71a79d5..dbfd4e6 100644 (file)
@@ -50,7 +50,7 @@ class ClangTUParser
 
   private:
     void detectFunctionBody(const char *s);
-    void writeLineNumber(CodeOutputInterface &ol,const FileDef *fd,uint line);
+    void writeLineNumber(CodeOutputInterface &ol,const FileDef *fd,uint line,bool writeLineAnchor);
     void codifyLines(CodeOutputInterface &ol,const FileDef *fd,const char *text,
                      uint &line,uint &column,const char *fontClass=0);
     void writeMultiLineCodeLink(CodeOutputInterface &ol,
index a349867..937c531 100644 (file)
@@ -285,7 +285,7 @@ class ClassDefImpl : public DefinitionMixin<ClassDefMutable>
     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,
+    virtual void writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup,int indentLevel,
                           const ClassDef *inheritedFrom,const QCString &inheritId) const;
     virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const;
     virtual void writeSummaryLinks(OutputList &ol) const;
@@ -326,13 +326,13 @@ class ClassDefImpl : public DefinitionMixin<ClassDefMutable>
                                           bool showAlways) 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 QCString &inheritId) const;
+    void writePlainMemberDeclaration(OutputList &ol,MemberListType lt,bool inGroup,
+                                     int indentLevel,const ClassDef *inheritedFrom,const QCString &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()) const;
     void writeIncludeFiles(OutputList &ol) const;
     void writeIncludeFilesForSlice(OutputList &ol) const;
-    //void writeAllMembersLink(OutputList &ol);
     void writeInheritanceGraph(OutputList &ol) const;
     void writeCollaborationGraph(OutputList &ol) const;
     void writeMemberGroups(OutputList &ol,bool showInline=FALSE) const;
@@ -1605,12 +1605,15 @@ int ClassDefImpl::countInheritanceNodes() const
 
 void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const
 {
+  static bool haveDot    = Config_getBool(HAVE_DOT);
+  static auto classGraph = Config_getEnum(CLASS_GRAPH);
+
+  if (classGraph == CLASS_GRAPH_t::NO) return;
   // count direct inheritance relations
   const int count=countInheritanceNodes();
 
   bool renderDiagram = FALSE;
-  if (Config_getBool(HAVE_DOT) &&
-      (Config_getBool(CLASS_DIAGRAMS) || Config_getBool(CLASS_GRAPH)))
+  if (haveDot && (classGraph==CLASS_GRAPH_t::YES || classGraph==CLASS_GRAPH_t::GRAPH))
     // write class diagram using dot
   {
     DotClassGraph inheritanceGraph(this,Inheritance);
@@ -1630,7 +1633,7 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const
       renderDiagram = TRUE;
     }
   }
-  else if (Config_getBool(CLASS_DIAGRAMS) && count>0)
+  else if ((classGraph==CLASS_GRAPH_t::YES || classGraph==CLASS_GRAPH_t::GRAPH) && count>0)
     // write class diagram using built-in generator
   {
     ClassDiagram diagram(this); // create a diagram of this class.
@@ -2083,7 +2086,7 @@ void ClassDefImpl::writeTagFile(TextStream &tagFile)
   if (isObjectiveC()) { tagFile << " objc=\"yes\""; }
   tagFile << ">\n";
   tagFile << "    <name>" << convertToXML(name()) << "</name>\n";
-  tagFile << "    <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>\n";
+  tagFile << "    <filename>" << convertToXML(addHtmlExtensionIfMissing(getOutputFileBase())) << "</filename>\n";
   if (!anchor().isEmpty())
   {
     tagFile << "    <anchor>" << convertToXML(anchor()) << "</anchor>\n";
@@ -2485,13 +2488,6 @@ void ClassDefImpl::writeDocumentationContents(OutputList &ol,const QCString & /*
   QCString pageType = " ";
   pageType += compoundTypeString();
 
-  Doxygen::indexList->addIndexItem(this,0);
-
-  if (Doxygen::searchIndex)
-  {
-    Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
-    Doxygen::searchIndex->addWord(localName(),TRUE);
-  }
   bool exampleFlag=hasExamples();
 
   //---------------------------------------- start flexible part -------------------------------
@@ -2770,7 +2766,7 @@ void ClassDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *current
           ol.writeString("<a class=\"navtab\" ");
           ol.writeString("href=\"");
           if (createSubDirs) ol.writeString("../../");
-          ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor());
+          ol.writeString(addHtmlExtensionIfMissing(md->getOutputFileBase())+"#"+md->anchor());
           ol.writeString("\">");
           ol.writeString(convertToHtml(md->name()));
           ol.writeString("</a>");
@@ -3227,7 +3223,7 @@ void ClassDefImpl::setRequiresClause(const QCString &req)
 /*! called from MemberDef::writeDeclaration() to (recursively) write the
  *  definition of an anonymous struct, union or class.
  */
-void ClassDefImpl::writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup,
+void ClassDefImpl::writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup,int indentLevel,
     const ClassDef *inheritedFrom,const QCString &inheritId) const
 {
   //printf("ClassName='%s' inGroup=%d\n",qPrint(name()),inGroup);
@@ -3254,7 +3250,7 @@ void ClassDefImpl::writeDeclaration(OutputList &ol,const MemberDef *md,bool inGr
   // write user defined member groups
   for (const auto &mg : m_impl->memberGroups)
   {
-    mg->writePlainDeclarations(ol,inGroup,this,0,0,0,inheritedFrom,inheritId);
+    mg->writePlainDeclarations(ol,inGroup,this,0,0,0,indentLevel,inheritedFrom,inheritId);
   }
 
   for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Class))
@@ -3262,7 +3258,7 @@ void ClassDefImpl::writeDeclaration(OutputList &ol,const MemberDef *md,bool inGr
     if (lde->kind()==LayoutDocEntry::MemberDecl)
     {
       const LayoutDocEntryMemberDecl *lmd = (const LayoutDocEntryMemberDecl*)lde.get();
-      writePlainMemberDeclaration(ol,lmd->type,inGroup,inheritedFrom,inheritId);
+      writePlainMemberDeclaration(ol,lmd->type,inGroup,indentLevel,inheritedFrom,inheritId);
     }
   }
 }
@@ -3971,9 +3967,9 @@ ClassDef *ClassDefImpl::insertTemplateInstance(const QCString &fileName,
           innerClass->setOuterScope(templateClass);
           innerClass->setHidden(isHidden());
           innerClass->setArtificial(TRUE);
-          freshInstance=TRUE;
         }
       }
+      freshInstance=TRUE;
     }
   }
   return templateClass;
@@ -4224,7 +4220,7 @@ int ClassDefImpl::countMemberDeclarations(MemberListType lt,const ClassDef *inhe
       for (const auto &mg : m_impl->memberGroups)
       {
         count+=mg->countGroupedInheritedMembers(lt);
-        if (lt2!=1) count+=mg->countGroupedInheritedMembers((MemberListType)lt2);
+        if (lt2!=-1) count+=mg->countGroupedInheritedMembers((MemberListType)lt2);
       }
     }
     static bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB);
@@ -4509,13 +4505,13 @@ void ClassDefImpl::writeSimpleMemberDocumentation(OutputList &ol,MemberListType
 
 void ClassDefImpl::writePlainMemberDeclaration(OutputList &ol,
          MemberListType lt,bool inGroup,
-         const ClassDef *inheritedFrom,const QCString &inheritId) const
+         int indentLevel,const ClassDef *inheritedFrom,const QCString &inheritId) const
 {
   //printf("%s: ClassDefImpl::writePlainMemberDeclaration()\n",qPrint(name()));
   MemberList * ml = getMemberList(lt);
   if (ml)
   {
-    ml->writePlainDeclarations(ol,inGroup,this,0,0,0,inheritedFrom,inheritId);
+    ml->writePlainDeclarations(ol,inGroup,this,0,0,0,indentLevel,inheritedFrom,inheritId);
   }
 }
 
index c1c66b5..7d9c22e 100644 (file)
@@ -446,7 +446,7 @@ class ClassDefMutable : public DefinitionMutable, public ClassDef
     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 QCString &inheritId) const = 0;
+                 int indentLevel, const ClassDef *inheritedFrom,const QCString &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;
index ed249b9..a5caede 100644 (file)
@@ -60,6 +60,7 @@ CommandMap cmdMap[] =
   { "internal",      CMD_INTERNAL },
   { "invariant",     CMD_INVARIANT },
   { "javalink",      CMD_JAVALINK },
+  { "javalinkplain", CMD_JAVALINK },
   { "latexinclude",  CMD_LATEXINCLUDE },
   { "latexonly",     CMD_LATEXONLY },
   { "li",            CMD_LI },
@@ -80,7 +81,6 @@ CommandMap cmdMap[] =
   { "return",        CMD_RETURN },
   { "returns",       CMD_RETURN },
   { "retval",        CMD_RETVAL },
-  { "rtfonly",       CMD_RTFONLY },
   { "sa",            CMD_SA },
   { "secreflist",    CMD_SECREFLIST },
   { "section",       CMD_SECTION },
@@ -151,6 +151,8 @@ CommandMap cmdMap[] =
   { "maninclude",    CMD_MANINCLUDE },
   { "xmlinclude",    CMD_XMLINCLUDE },
   { "iline",         CMD_ILINE },
+  { "iliteral",      CMD_ILITERAL },
+  { "endiliteral",   CMD_ENDILITERAL },
   { 0,               0 },
 };
 
@@ -163,6 +165,7 @@ CommandMap htmlTagMap[] =
   { "table",      HTML_TABLE },
   { "caption",    HTML_CAPTION },
   { "small",      HTML_SMALL },
+  { "cite",       HTML_CITE },
   { "code",       HTML_CODE },
   { "dfn",        HTML_CODE },
   { "var",        HTML_EMPHASIS },
@@ -202,6 +205,7 @@ CommandMap htmlTagMap[] =
   { "u",          HTML_UNDERLINE },
   { "ins",        HTML_INS },
   { "del",        HTML_DEL },
+  { "details",    HTML_DETAILS },
 
   { "c",            XML_C },
   // { "code",       XML_CODE },  <= ambiguous <code> is also a HTML tag
index 7ee451c..619470a 100644 (file)
@@ -143,6 +143,8 @@ enum CommandType
   CMD_MANINCLUDE   = 114,
   CMD_XMLINCLUDE   = 115,
   CMD_ILINE        = 116,
+  CMD_ILITERAL     = 117,
+  CMD_ENDILITERAL  = 118,
 };
 
 enum HtmlTagType
@@ -186,6 +188,8 @@ enum HtmlTagType
   HTML_INS       = 36,
   HTML_DEL       = 37,
   HTML_S         = 38,
+  HTML_DETAILS   = 39,
+  HTML_CITE      = 40,
 
   XML_CmdMask    = 0x100,
 
index f15f3f7..687f52e 100644 (file)
@@ -46,7 +46,8 @@ class CCodeParser : public CodeParserInterface
                    bool collectXRefs=TRUE
                   );
     void resetCodeParserState();
-    void setStartCodeLine(const bool inp);
+    void setInsideCodeLine(bool inp);
+    bool insideCodeLine() const;
   private:
     struct Private;
     std::unique_ptr<Private> p;
index 9af97b8..a0054ab 100644 (file)
 %option extra-type="struct codeYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -30,6 +34,7 @@
 #include <memory>
 #include <algorithm>
 #include <unordered_map>
+#include <unordered_set>
 #include <stack>
 #include <vector>
 #include <string>
@@ -98,17 +103,13 @@ struct codeYY_state
   QCString      parmType;
   QCString      parmName;
 
-  bool          beginCodeLine = true; //!< signals whether or not we should with the first line
-                                      //!< write a start line code or not. Essential
-                                      //!< when this code parser is called from another 
-                                      //!< code parser.
-
   const char *  inputString = 0;     //!< the code fragment as text
   yy_size_t     inputPosition = 0;   //!< read offset during parsing
+  QCString      fileName;
   int           inputLines = 0;      //!< number of line in the code fragment
   int           yyLineNr = 0;        //!< current line number
   yy_size_t     yyColNr = 0;         //!< current column number
-  bool          needsTermination = FALSE;
+  bool          insideCodeLine = FALSE;
 
   bool          exampleBlock = FALSE;
   QCString      exampleName;
@@ -188,7 +189,7 @@ static bool isCastKeyword(const char *s);
 
 //-------------------------------------------------------------------
 #if USE_STATE2STRING
-static const char *stateToString(yyscan_t yyscanner,int state);
+static const char *stateToString(int state);
 #endif
 
 static void saveObjCContext(yyscan_t yyscanner);
@@ -264,6 +265,9 @@ static std::mutex g_usingDirectiveMutex;
 #undef  YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
 
 %}
 
@@ -277,10 +281,11 @@ TEMPLIST "<"[^\"\}\{\(\)\/\n\>]*">"
 SCOPETNAME (((({ID}{TEMPLIST}?){BN}*)?{SEP}{BN}*)*)((~{BN}*)?{ID})
 SCOPEPREFIX ({ID}{TEMPLIST}?{BN}*{SEP}{BN}*)+
 KEYWORD_OBJC ("@public"|"@private"|"@protected"|"@class"|"@implementation"|"@interface"|"@end"|"@selector"|"@protocol"|"@optional"|"@required"|"@throw"|"@synthesize"|"@property")
-KEYWORD ("asm"|"__assume"|"auto"|"class"|"const"|"delete"|"enum"|"explicit"|"extern"|"false"|"friend"|"gcnew"|"gcroot"|"set"|"get"|"inline"|"internal"|"mutable"|"namespace"|"new"|"null"|"nullptr"|"override"|"operator"|"pin_ptr"|"private"|"protected"|"public"|"raise"|"register"|"remove"|"self"|"sizeof"|"static"|"struct"|"__super"|"function"|"template"|"generic"|"this"|"true"|"typedef"|"typeid"|"typename"|"union"|"using"|"virtual"|"volatile"|"abstract"|"final"|"import"|"synchronized"|"transient"|"alignas"|"alignof"|"concept"|"requires"|"decltype"|{KEYWORD_OBJC}|"constexpr"|"consteval"|"constinit"|"co_await"|"co_return"|"co_yield"|"static_assert"|"noexcept"|"thread_local")
+  /* please also pay attention to skipLanguageSpecificKeyword when changing the list of keywords. */
+KEYWORD ("asm"|"__assume"|"auto"|"class"|"const"|"delete"|"enum"|"explicit"|"extern"|"false"|"friend"|"gcnew"|"gcroot"|"set"|"get"|"inline"|"internal"|"mutable"|"namespace"|"new"|"null"|"nullptr"|"override"|"operator"|"pin_ptr"|"private"|"protected"|"public"|"raise"|"register"|"remove"|"self"|"sizeof"|"static"|"struct"|"__super"|"function"|"template"|"generic"|"this"|"true"|"typedef"|"typeid"|"typename"|"union"|"using"|"virtual"|"volatile"|"abstract"|"final"|"import"|"synchronized"|"transient"|"alignas"|"alignof"|"concept"|"requires"|"decltype"|{KEYWORD_OBJC}|"constexpr"|"consteval"|"constinit"|"co_await"|"co_return"|"co_yield"|"static_assert"|"noexcept"|"thread_local"|"enum"{B}+("class"|"struct"))
 FLOWKW  ("break"|"catch"|"continue"|"default"|"do"|"else"|"finally"|"return"|"switch"|"throw"|"throws"|"@catch"|"@finally")
 FLOWCONDITION  ("case"|"for"|"foreach"|"for each"|"goto"|"if"|"try"|"while"|"@try")
-TYPEKW  ("bool"|"byte"|"char"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr")
+TYPEKW  ("bool"|"byte"|"char"|"char8_t"|"char16_t"|"char32_t"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr")
 TYPEKWSL ("LocalObject"|"Object"|"Value")
 CASTKW ("const_cast"|"dynamic_cast"|"reinterpret_cast"|"static_cast")
 CHARLIT   (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^' \\\n]{1,4}"'"))
@@ -343,7 +348,6 @@ ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"seale
 %x      SkipComment
 %x      SkipCxxComment
 %x      RemoveSpecialCComment
-%x      StripSpecialCComment
 %x      Body
 %x      FuncCall
 %x      MemberCall
@@ -1529,7 +1533,7 @@ ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"seale
                                           yyextra->code->codify(yytext);
                                           endFontClass(yyscanner);
                                         }
-<MemberCall2,FuncCall>{ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* {
+<MemberCall2,FuncCall>("::")?{ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* {
                                           if (isCastKeyword(yytext))
                                           {
                                             REJECT;
@@ -1939,7 +1943,7 @@ ENDQopt ("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"seale
                                             BEGIN( yyextra->lastCContext ) ;
                                           }
                                         }
-<SkipCPP>\n/.*\n                        {
+<SkipCPP>\n/(.|\n)                      {
                                           endFontClass(yyscanner);
                                           BEGIN( yyextra->lastSkipCppContext ) ;
                                           unput('\n');
@@ -2371,24 +2375,26 @@ static void startCodeLine(yyscan_t yyscanner)
         yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
                                 yyextra->currentMemberDef->getOutputFileBase(),
                                 yyextra->currentMemberDef->anchor(),
-                                yyextra->yyLineNr);
+                                yyextra->yyLineNr,!yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
       else if (d->isLinkableInProject())
       {
         yyextra->code->writeLineNumber(d->getReference(),
                                 d->getOutputFileBase(),
-                                QCString(),yyextra->yyLineNr);
+                                QCString(),yyextra->yyLineNr,!yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
     }
     else
     {
-      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr);
+      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr,
+                                     !yyextra->includeCodeFragment);
     }
   }
   DBG_CTX((stderr,"startCodeLine(%d)\n",yyextra->yyLineNr));
   yyextra->code->startCodeLine(yyextra->sourceFileDef && yyextra->lineNumbers);
+  yyextra->insideCodeLine = true;
   if (yyextra->currentFontClass)
   {
     yyextra->code->startFontClass(QCString(yyextra->currentFontClass));
@@ -2403,13 +2409,17 @@ static void endCodeLine(yyscan_t yyscanner)
   DBG_CTX((stderr,"endCodeLine(%d)\n",yyextra->yyLineNr));
   endFontClass(yyscanner);
   yyextra->code->endCodeLine();
+  yyextra->insideCodeLine = false;
 }
 
 static void nextCodeLine(yyscan_t yyscanner)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   const char * fc = yyextra->currentFontClass;
-  endCodeLine(yyscanner);
+  if (yyextra->insideCodeLine)
+  {
+    endCodeLine(yyscanner);
+  }
   if (yyextra->yyLineNr<yyextra->inputLines)
   {
     yyextra->currentFontClass = fc;
@@ -3349,9 +3359,7 @@ static int countLines(yyscan_t yyscanner)
   }
   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++,
-    yyextra->needsTermination=TRUE;
+    count++;
   }
   return count;
 }
@@ -3726,8 +3734,41 @@ static QCString escapeComment(yyscan_t yyscanner,const char *s)
 static bool skipLanguageSpecificKeyword(yyscan_t yyscanner,const char *keyword)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
-  QCString kw(keyword);
-  return yyextra->lang==SrcLangExt_Cpp && (kw == "remove" || kw == "set" || kw == "get");
+  static std::unordered_set<std::string> non_cpp_keywords = {
+    "__assume", "__super", "abstract", "function",
+    "gcnew", "gcroot", "generic", "get",
+    "internal", "null", "pin_ptr", "raise",
+    "remove", "self", "set", "transient"};
+  static std::unordered_set<std::string> non_java_keywords = {
+    "alignas", "alignof", "and", "and_eq", "asm",
+    "atomic_cancel", "atomic_commit", "atomic_noexcept", "auto", "bitand",
+    "bitor", "bool", "char8_t", "char16_t", "char32_t",
+    "compl", "concept", "consteval", "constexpr", "constinit",
+    "const_cast", "co_await", "co_return", "co_yield", "decltype",
+    "delete", "dynamic_cast", "explicit", "export", "extern",
+    "friend", "inline", "mutable", "namespace", "noexcept",
+    "not", "not_eq", "nullptr", "operator", "or",
+    "or_eq", "reflexpr", "register", "reinterpret_cast", "requires",
+    "signed", "sizeof", "static_assert", "static_cast", "struct",
+    "template", "thread_local", "typedef", "typeid", "typename",
+    "union", "unsigned", "using", "virtual", "wchar_t",
+    "xor", "xor_eq",
+    "override"
+  };
+  bool retval;
+  switch (yyextra->lang)
+  {
+    case SrcLangExt_Cpp:
+      retval = (non_cpp_keywords.find(keyword) != non_cpp_keywords.end());
+      break;
+    case SrcLangExt_Java:
+      retval = (non_java_keywords.find(keyword) != non_java_keywords.end());
+      break;
+    default: 
+      retval = false;
+      break;
+  }
+  return retval;
 }
 
 static bool isCastKeyword(const char *keyword)
@@ -3833,12 +3874,19 @@ void CCodeParser::resetCodeParserState()
   yyextra->codeClassMap.clear();
   yyextra->curClassBases.clear();
   yyextra->anchorCount = 0;
+  yyextra->insideCodeLine = false;
 }
 
-void CCodeParser::setStartCodeLine(const bool inp)
+void CCodeParser::setInsideCodeLine(bool inp)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
-  yyextra->beginCodeLine = inp;
+  yyextra->insideCodeLine = inp;
+}
+
+bool CCodeParser::insideCodeLine() const
+{
+  struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
+  return yyextra->insideCodeLine;
 }
 
 void CCodeParser::parseCode(CodeOutputInterface &od,const QCString &className,const QCString &s,
@@ -3858,10 +3906,10 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const QCString &className,co
 
   yyextra->code = &od;
   yyextra->inputString   = s.data();
+  yyextra->fileName      = fd ? fd->fileName():"";
   yyextra->inputPosition = 0;
   codeYYrestart(0,yyscanner);
   yyextra->currentFontClass = 0;
-  yyextra->needsTermination = FALSE;
   yyextra->searchCtx = searchCtx;
   yyextra->collectXRefs = collectXRefs;
   yyextra->inFunctionTryBlock = FALSE;
@@ -3915,7 +3963,10 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const QCString &className,co
   }
   yyextra->includeCodeFragment = inlineFragment;
   DBG_CTX((stderr,"** exBlock=%d exName=%s include=%d\n",exBlock,qPrint(exName),inlineFragment));
-  if (yyextra->beginCodeLine) startCodeLine(yyscanner);
+  if (!yyextra->insideCodeLine)
+  {
+    startCodeLine(yyscanner);
+  }
   yyextra->type.resize(0);
   yyextra->name.resize(0);
   yyextra->args.resize(0);
@@ -3925,11 +3976,9 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const QCString &className,co
   BEGIN( Body );
   codeYYlex(yyscanner);
   yyextra->lexInit=TRUE;
-  if (yyextra->needsTermination)
+  if (yyextra->insideCodeLine)
   {
-    endFontClass(yyscanner);
-    DBG_CTX((stderr,"endCodeLine(%d)\n",yyextra->yyLineNr));
-    yyextra->code->endCodeLine();
+    endCodeLine(yyscanner);
   }
   if (cleanupSourceDef)
   {
@@ -3941,7 +3990,6 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const QCString &className,co
   yyextra->tooltipManager.writeTooltips(od);
 
   printlex(yy_flex_debug, FALSE, __FILE__, fd ? qPrint(fd->fileName()): NULL);
-  return;
 }
 
 #if USE_STATE2STRING
index aaf1162..ad9b302 100644 (file)
 %option extra-type="struct commentcnvYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -48,9 +52,9 @@
 
 #define USE_STATE2STRING 0
   
-struct CondCtx
+struct commentcnvYY_CondCtx
 {
-  CondCtx(int line,QCString id,bool b) 
+  commentcnvYY_CondCtx(int line,QCString id,bool b) 
     : lineNr(line),sectionId(id), skip(b) {}
   int lineNr;
   QCString sectionId;
@@ -77,7 +81,7 @@ struct commentcnvYY_state
   QCString fileName;
   int      lineNr = 0;
   int      condCtx = 0;
-  std::stack<CondCtx> condStack;
+  std::stack<commentcnvYY_CondCtx> condStack;
   std::stack<int> commentStack;
   QCString blockName;
   int      lastCommentContext = 0;
@@ -122,10 +126,13 @@ static void clearCommentStack(yyscan_t yyscanner);
 #undef  YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
 
 %}
 
-MAILADR   ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+
+MAILADDR   ("mailto:")?[a-z_A-Z0-9\x80-\xff.+-]+"@"[a-z_A-Z0-9\x80-\xff-]+("."[a-z_A-Z0-9\x80-\xff\-]+)+[a-z_A-Z0-9\x80-\xff\-]+
 
 %option noyywrap
 
@@ -406,12 +413,19 @@ SLASHopt [/]*
                                        yyextra->commentStack.push(yyextra->lineNr);
                                     }
                                   }
-<CComment,CNComment,ReadLine>{MAILADR}      |
-<CComment,CNComment,ReadLine>"<"{MAILADR}">" { // Mail address, to prevent seeing e.g x@code-factory.org as start of a code block
+<CComment,CNComment,ReadLine>{MAILADDR}       |
+<CComment,CNComment,ReadLine>"<"{MAILADDR}">" { // Mail address, to prevent seeing e.g x@code-factory.org as start of a code block
                                      copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
-<CComment>"{@code"/[ \t\n]        {
-                                     copyToOutput(yyscanner,"@code",5); 
+<CComment>"{"[ \t]*"@code"/[ \t\n] {
+                                     copyToOutput(yyscanner,"@iliteral{code}",15); 
+                                    yyextra->lastCommentContext = YY_START;
+                                    yyextra->javaBlock=1;
+                                    yyextra->blockName=&yytext[1];
+                                     BEGIN(VerbatimCode);
+                                  }
+<CComment>"{"[ \t]*"@literal"/[ \t\n] {
+                                     copyToOutput(yyscanner,"@iliteral",9); 
                                     yyextra->lastCommentContext = YY_START;
                                     yyextra->javaBlock=1;
                                     yyextra->blockName=&yytext[1];
@@ -460,7 +474,7 @@ SLASHopt [/]*
                                     yyextra->lastCommentContext = YY_START;
                                     BEGIN(Verbatim);
                                   }
-<CComment,ReadLine>[\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */
+<CComment,ReadLine>[\\@]("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */
                                      copyToOutput(yyscanner,yytext,(int)yyleng); 
                                     yyextra->blockName=&yytext[1];
                                     yyextra->lastCommentContext = YY_START;
@@ -475,7 +489,7 @@ SLASHopt [/]*
 <Scan>.                            { /* any other character */
                                      copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
-<Verbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}"|"f)") { /* end of verbatim block */
+<Verbatim>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}"|"f)") { /* end of verbatim block */
                                      copyToOutput(yyscanner,yytext,(int)yyleng);
                                     if (&yytext[1]==yyextra->blockName) // end of formula
                                     {
@@ -507,7 +521,7 @@ SLASHopt [/]*
                                       yyextra->javaBlock--;
                                       if (yyextra->javaBlock==0)
                                       {
-                                         copyToOutput(yyscanner," @endcode ",10);
+                                         copyToOutput(yyscanner," @endiliteral ",14);
                                         BEGIN(yyextra->lastCommentContext);
                                       }
                                       else
@@ -876,9 +890,10 @@ SLASHopt [/]*
                                     yyextra->condCtx=YY_START;
                                      handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
                                    }
+<CondLine>\n                      |
 <CondLine>.                       { // forgot section id?
                                      handleCondSectionId(yyscanner," "); // fake section id causing the section to be hidden unconditionally
-                                    if (*yytext=='\n') yyextra->lineNr++;
+                                    if (*yytext=='\n') { yyextra->lineNr++; copyToOutput(yyscanner,"\n",1);}
                                   }
 <CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*  { // expand alias without arguments
                                     replaceAliases(yyscanner,QCString(yytext));
@@ -944,6 +959,9 @@ SLASHopt [/]*
 <*>.                               {
                                     copyToOutput(yyscanner,yytext,(int)yyleng);
                                    }
+  /*
+<*>\n  { fprintf(stderr,"Lex scanner %s (%s) default rule newline for state %s.\n", __FILE__, qPrint(yyextra->fileName),stateToString(YY_START));}
+  */
 %%
 
 static void replaceCommentMarker(yyscan_t yyscanner,const char *s,int len)
@@ -1057,7 +1075,7 @@ static void startCondSection(yyscan_t yyscanner,const QCString &sectId)
   //printf("startCondSection: skip=%d stack=%d\n",g_skip,g_condStack.count());
   CondParser prs;
   bool expResult = prs.parse(yyextra->fileName,yyextra->lineNr,sectId);
-  yyextra->condStack.push(CondCtx(yyextra->lineNr,sectId,yyextra->skip));
+  yyextra->condStack.push(commentcnvYY_CondCtx(yyextra->lineNr,sectId,yyextra->skip));
   if (!expResult) // not enabled
   {
     yyextra->skip=TRUE;
@@ -1074,7 +1092,7 @@ static void endCondSection(yyscan_t yyscanner)
   }
   else
   {
-    const CondCtx &ctx = yyextra->condStack.top();
+    const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
     yyextra->skip=ctx.skip;
     yyextra->condStack.pop();
   }
@@ -1205,7 +1223,7 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const QCString &fileName)
   yylex(yyscanner);
   while (!yyextra->condStack.empty())
   {
-    const CondCtx &ctx = yyextra->condStack.top();
+    const commentcnvYY_CondCtx &ctx = yyextra->condStack.top();
     QCString sectionInfo(" ");
     if (ctx.sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",ctx.sectionId.stripWhiteSpace().data());
     warn(yyextra->fileName,ctx.lineNr,"Conditional section%sdoes not have "
index 23af80f..1974732 100644 (file)
 %option extra-type="struct commentscanYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve typesafety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -83,6 +87,7 @@ static bool handleFile(yyscan_t yyscanner,const QCString &, const StringVector &
 static bool handleDir(yyscan_t yyscanner,const QCString &, const StringVector &);
 static bool handleExample(yyscan_t yyscanner,const QCString &, const StringVector &);
 static bool handleDetails(yyscan_t yyscanner,const QCString &, const StringVector &);
+static bool handleRaiseWarning(yyscan_t yyscanner,const QCString &, const StringVector &);
 static bool handleNoop(yyscan_t yyscanner,const QCString &, const StringVector &);
 static bool handleName(yyscan_t yyscanner,const QCString &, const StringVector &);
 static bool handleTodo(yyscan_t yyscanner,const QCString &, const StringVector &);
@@ -255,6 +260,7 @@ static const std::map< std::string, DocCmdMap > docCmdMap =
   { "public",          { &handlePublic,           CommandSpacing::Invisible }},
   { "publicsection",   { &handlePublicSection,    CommandSpacing::Invisible }},
   { "pure",            { &handlePure,             CommandSpacing::Invisible }},
+  { "raisewarning",    { &handleRaiseWarning,     CommandSpacing::Invisible }},
   { "refitem",         { &handleRefItem,          CommandSpacing::Inline    }},
   { "related",         { &handleRelated,          CommandSpacing::Invisible }},
   { "relatedalso",     { &handleRelatedAlso,      CommandSpacing::Invisible }},
@@ -301,7 +307,8 @@ static const std::map< std::string, DocCmdMap > docCmdMap =
   { "weakgroup",       { &handleWeakGroup,        CommandSpacing::Invisible }},
   { "xmlinclude",      { 0,                       CommandSpacing::Inline    }},
   { "xmlonly",         { &handleFormatBlock,      CommandSpacing::Invisible }},
-  { "xrefitem",        { &handleXRefItem,         CommandSpacing::XRef      }}
+  { "xrefitem",        { &handleXRefItem,         CommandSpacing::XRef      }},
+  { "iliteral",        { &handleFormatBlock,      CommandSpacing::Inline    }},
 };
 
 #define YY_NO_INPUT 1
@@ -402,12 +409,15 @@ struct commentscanYY_state
 
   QCString         guardExpr;
   int              roundCount = 0;
+  int              HTMLDetails = 0;
 
   bool             insideParBlock = FALSE;
   bool             inInternalDocs = FALSE;
   int              prevPosition = 0;
   DocGroup         docGroup;
   bool             markdownSupport = TRUE;
+
+  QCString         raiseWarning;
 };
 
 
@@ -449,6 +459,10 @@ static void addIline(yyscan_t yyscanner,int lineNr);
 #undef        YY_INPUT
 #define        YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
+
 %}
 
        /* start command character */
@@ -467,8 +481,11 @@ CODE      [cC][oO][dD][eE]
 CAPTION   [cC][aA][pP][tT][iI][oO][nN]
 CENTER    [cC][eE][nN][tT][eE][rR]
 DIV       [dD][iI][vV]
+DETAILS   [dD][eE][tT][aA][iI][lL][sS]
 DETAILEDHTML {CENTER}|{DIV}|{PRE}|{UL}|{TABLE}|{OL}|{DL}|{P}|[Hh][1-6]|{IMG}|{HR}|{PARA}
 DETAILEDHTMLOPT {CODE}
+SUMMARY   [sS][uU][mM][mM][aA][rR][yY]
+REMARKS   [rR][eE][mM][aA][rR][kK][sS]
 BN        [ \t\n\r]
 BL        [ \t\r]*"\n"
 B         [ \t]
@@ -489,7 +506,7 @@ CITEID    {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*|"\""{CITESCHAR}{C
 SCOPEID   {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
 SCOPENAME "$"?(({ID}?{BN}*("::"|"."){BN}*)*)((~{BN}*)?{ID})
 TMPLSPEC  "<"{BN}*[^>]+{BN}*">"
-MAILADDR   [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+
+MAILADDR  ("mailto:")?[a-z_A-Z0-9\x80-\xff.+-]+"@"[a-z_A-Z0-9\x80-\xff-]+("."[a-z_A-Z0-9\x80-\xff\-]+)+[a-z_A-Z0-9\x80-\xff\-]+
 RCSTAG    "$"{ID}":"[^\n$]+"$"
 
   // C start comment 
@@ -553,6 +570,7 @@ STopt  [^\n@\\]*
 %x      GuardExpr
 %x      CdataSection
 %x      Noop
+%x      RaiseWarning
 
 %%
 
@@ -601,19 +619,28 @@ STopt  [^\n@\\]*
                                           // continue with the same input
                                           REJECT;
                                         }
-<Comment>"<summary>"                    { // start of a .NET XML style brief description
-                                          setOutput(yyscanner,OutputBrief);
+<Comment>"<"{DETAILS}{ATTR}">"          { // start of a HTML style details description
+                                          yyextra->HTMLDetails++;
+                                          setOutput(yyscanner,OutputDoc);
                                           addOutput(yyscanner,yytext);
                                         }
-<Comment>"<remarks>"                    { // start of a .NET XML style detailed description
-                                          setOutput(yyscanner,OutputDoc);
+<Comment>"</"{DETAILS}">"               { // end of a HTML style details description
+                                          if (yyextra->HTMLDetails) yyextra->HTMLDetails--;
                                           addOutput(yyscanner,yytext);
                                         }
-<Comment>"</summary>"                   { // start of a .NET XML style detailed description
+<Comment>"<"{SUMMARY}">"                { // start of a .NET XML style brief description
+                                          if (!yyextra->HTMLDetails) setOutput(yyscanner,OutputBrief);
                                           addOutput(yyscanner,yytext);
+                                        }
+<Comment>"<"{REMARKS}">"                { // start of a .NET XML style detailed description
                                           setOutput(yyscanner,OutputDoc);
+                                          addOutput(yyscanner,yytext);
                                         }
-<Comment>"</remarks>"                   { // end of a brief or detailed description
+<Comment>"</"{SUMMARY}">"               { // start of a .NET XML style detailed description
+                                          addOutput(yyscanner,yytext);
+                                          if (!yyextra->HTMLDetails) setOutput(yyscanner,OutputDoc);
+                                        }
+<Comment>"</"{REMARKS}">"               { // end of a brief or detailed description
                                           setOutput(yyscanner,OutputDoc);
                                           addOutput(yyscanner,yytext);
                                         }
@@ -737,7 +764,7 @@ STopt  [^\n@\\]*
 <Comment>{B}*{CMD}"~"[a-z_A-Z-]*        { // language switch command
                                           QCString langId = QCString(yytext).stripWhiteSpace().mid(2);
                                           if (!langId.isEmpty() &&
-                                              qstricmp(Config_getEnum(OUTPUT_LANGUAGE).data(),langId.data())!=0)
+                                              qstricmp(Config_getEnumAsString(OUTPUT_LANGUAGE).data(),langId.data())!=0)
                                           { // enable language specific section
                                             BEGIN(SkipLang);
                                           }
@@ -1003,7 +1030,8 @@ STopt  [^\n@\\]*
   /* ------------ handle argument of namespace command --------------- */
 
 <NameSpaceDocArg1>{SCOPENAME}           { // handle argument
-                                          yyextra->current->name = substitute(QCString(yytext),QCString("."),QCString("::"));
+                                          lineCount(yyscanner);
+                                          yyextra->current->name = substitute(removeRedundantWhiteSpace(QCString(yytext)),QCString("."),QCString("::"));
                                           BEGIN( Comment );
                                         }
 <NameSpaceDocArg1>{LC}                  { // line continuation
@@ -1071,10 +1099,12 @@ STopt  [^\n@\\]*
   /* ------ handle argument of class/struct/union command --------------- */
 
 <ClassDocArg1>{SCOPENAME}{TMPLSPEC}     {
+                                          lineCount(yyscanner);
                                           yyextra->current->name = substitute(removeRedundantWhiteSpace(QCString(yytext)),".","::");
                                           BEGIN( ClassDocArg2 );
                                         }
 <ClassDocArg1>{SCOPENAME}               { // first argument
+                                          lineCount(yyscanner);
                                           yyextra->current->name = substitute(QCString(yytext),".","::");
                                           if (yyextra->current->section==Entry::PROTOCOLDOC_SEC)
                                           {
@@ -1084,6 +1114,7 @@ STopt  [^\n@\\]*
                                           BEGIN( ClassDocArg2 );
                                         }
 <CategoryDocArg1>{SCOPENAME}{B}*"("[^\)]+")" {
+                                          lineCount(yyscanner);
                                           yyextra->current->name = substitute(QCString(yytext),".","::");
                                           BEGIN( ClassDocArg2 );
                                         }
@@ -1487,7 +1518,7 @@ STopt  [^\n@\\]*
 
   /* ----- handle arguments of the preformatted block commands ------- */
 
-<FormatBlock>{CMD}("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"endmsc")/{NW} { // possible ends
+<FormatBlock>{CMD}("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"endmsc")/{NW} { // possible ends
                                           addOutput(yyscanner,yytext);
                                           if (&yytext[4]==yyextra->blockName) // found end of the block
                                           {
@@ -1509,12 +1540,12 @@ STopt  [^\n@\\]*
                                           addOutput(yyscanner,'\n');
                                         }
 <FormatBlock>{CCS}                       { // start of a C-comment
-                                          if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim")) yyextra->commentCount++;
+                                          if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim" || yyextra->blockName=="iliteral")) yyextra->commentCount++;
                                           addOutput(yyscanner,yytext);
                                         }
 <FormatBlock>{CCE}                       { // end of a C-comment
                                           addOutput(yyscanner,yytext);
-                                          if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim"))
+                                          if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim" || yyextra->blockName=="iliteral"))
                                           {
                                             yyextra->commentCount--;
                                             if (yyextra->commentCount<0)
@@ -1760,6 +1791,18 @@ STopt  [^\n@\\]*
                                         }
 <Noop>.                                 { // ignore other stuff
                                         }
+  /* ----- handle argument of raisewarning command ------- */
+<RaiseWarning>{DOCNL}                   { // end of argument
+                                          warn_doc_error(yyextra->fileName,yyextra->lineNr,
+                                                         "%s",qPrint(yyextra->raiseWarning));
+                                          yyextra->raiseWarning = "";
+                                          if (*yytext=='\n') yyextra->lineNr++;
+                                          addOutput(yyscanner,'\n');
+                                          BEGIN( Comment );
+                                        }
+<RaiseWarning>.                         { // ignore other stuff
+                                          yyextra->raiseWarning += yytext;
+                                        }
   /* ----- handle argument of ingroup command ------- */
 
 <InGroupParam>{LABELID}                 { // group id
@@ -1893,7 +1936,7 @@ STopt  [^\n@\\]*
 <SkipLang>[\\@]"~"[a-zA-Z-]*            { /* language switch */
                                           QCString langId(&yytext[2]);
                                           if (langId.isEmpty() ||
-                                              qstricmp(Config_getEnum(OUTPUT_LANGUAGE).data(),langId.data())==0)
+                                              qstricmp(Config_getEnumAsString(OUTPUT_LANGUAGE).data(),langId.data())==0)
                                           { // enable language specific section
                                             BEGIN(Comment);
                                           }
@@ -1931,20 +1974,41 @@ STopt  [^\n@\\]*
 
   /* ----- handle argument of the copydoc command ------- */
 
-<CopyDoc><<EOF>>                        |
-<CopyDoc>{DOCNL}                        {
-                                          if (*yytext=='\n') yyextra->lineNr++;
-                                          addOutput(yyscanner,'\n');
+<CopyDoc><<EOF>>                        {
                                           setOutput(yyscanner,OutputDoc);
-                                          addOutput(yyscanner," \\copydetails ");
+                                          addOutput(yyscanner," \\ilinebr\\ilinebr\\copydetails ");
                                           addOutput(yyscanner,yyextra->copyDocArg);
                                           addOutput(yyscanner,"\n");
                                           BEGIN(Comment);
                                         }
-<CopyDoc>[^\n\\]+                       {
+<CopyDoc>{DOCNL}                        {
+                                          if (*yytext=='\n') yyextra->lineNr++;
+                                          if (yyextra->braceCount==0)
+                                          {
+                                            setOutput(yyscanner,OutputDoc);
+                                            addOutput(yyscanner," \\ilinebr\\ilinebr\\copydetails ");
+                                            addOutput(yyscanner,yyextra->copyDocArg);
+                                            addOutput(yyscanner,"\n");
+                                            BEGIN(Comment);
+                                          }
+                                        }
+<CopyDoc>{LC}                           { // line continuation
+                                          yyextra->lineNr++;
+                                        }
+<CopyDoc>[^@\\\n()]+                    { // non-special characters
                                           yyextra->copyDocArg+=yytext;
                                           addOutput(yyscanner,yytext);
                                         }
+<CopyDoc>"("                            {
+                                          yyextra->copyDocArg+=yytext;
+                                          addOutput(yyscanner,yytext);
+                                          yyextra->braceCount++;
+                                        }
+<CopyDoc>")"                            {
+                                          yyextra->copyDocArg+=yytext;
+                                          addOutput(yyscanner,yytext);
+                                          yyextra->braceCount--;
+                                        }
 <CopyDoc>.                              {
                                           yyextra->copyDocArg+=yytext;
                                           addOutput(yyscanner,yytext);
@@ -2139,6 +2203,7 @@ static bool handleMainpage(yyscan_t yyscanner,const QCString &, const StringVect
   {
     yyextra->current->name = "mainpage";
   }
+  setOutput(yyscanner,OutputDoc);
   BEGIN( PageDocArg2 );
   return stop;
 }
@@ -2216,6 +2281,14 @@ static bool handleDetails(yyscan_t yyscanner,const QCString &, const StringVecto
   return FALSE;
 }
 
+static bool handleRaiseWarning(yyscan_t yyscanner,const QCString &, const StringVector &)
+{
+  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+  yyextra->raiseWarning = "";
+  BEGIN( RaiseWarning );
+  return FALSE;
+}
+
 static bool handleNoop(yyscan_t yyscanner,const QCString &, const StringVector &)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
@@ -2324,6 +2397,7 @@ static bool handleRelated(yyscan_t yyscanner,const QCString &cmd, const StringVe
         "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition");
   }
   yyextra->current->relatesType = Simple;
+  yyextra->currentCmd = cmd;
   BEGIN(RelatesParam1);
   return FALSE;
 }
@@ -2823,7 +2897,12 @@ static bool handleCopyDetails(yyscan_t yyscanner,const QCString &, const StringV
 static bool handleCopyDoc(yyscan_t yyscanner,const QCString &, const StringVector &)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
-  setOutput(yyscanner,OutputBrief);
+  if (yyextra->current->brief.isEmpty() && yyextra->current->doc.isEmpty())
+  { // if we don't have a brief or detailed description yet,
+    // then the @copybrief should end up in the brief description.
+    // otherwise it will be copied inline (see bug691315 & bug700788)
+    setOutput(yyscanner,OutputBrief);
+  }
   if (!yyextra->spaceBeforeCmd.isEmpty())
   {
     addOutput(yyscanner,yyextra->spaceBeforeCmd);
@@ -2831,6 +2910,7 @@ static bool handleCopyDoc(yyscan_t yyscanner,const QCString &, const StringVecto
   }
   addOutput(yyscanner,"\\copybrief ");
   yyextra->copyDocArg.resize(0);
+  yyextra->braceCount = 0;
   BEGIN(CopyDoc);
   return FALSE;
 }
@@ -3202,6 +3282,7 @@ static inline void setOutput(yyscan_t yyscanner,OutputContext ctx)
       if (oldContext!=yyextra->inContext)
       {
         stripTrailingWhiteSpace(yyextra->current->doc);
+        if (yyextra->current->doc.isEmpty()) yyextra->current->docLine = yyextra->lineNr;
         if (yyextra->current->docFile.isEmpty())
         {
           yyextra->current->docFile = yyextra->fileName;
@@ -3213,6 +3294,7 @@ static inline void setOutput(yyscan_t yyscanner,OutputContext ctx)
     case OutputBrief:
       if (oldContext!=yyextra->inContext)
       {
+        if (yyextra->current->brief.isEmpty()) yyextra->current->briefLine = yyextra->lineNr;
         if (yyextra->current->briefFile.isEmpty())
         {
           yyextra->current->briefFile = yyextra->fileName;
@@ -3304,8 +3386,8 @@ static inline void addOutput(yyscan_t yyscanner,char c)
 
 static void addIline(yyscan_t yyscanner,int lineNr)
 {
-  char cmd[20];
-  sprintf(cmd,"\\iline %d ",lineNr);
+  char cmd[30];
+  sprintf(cmd,"\\iline %d \\ilinebr ",lineNr);
   addOutput(yyscanner, cmd);
 }
 
index c9c886e..977f569 100644 (file)
@@ -54,6 +54,7 @@ class ConceptDefImpl : public DefinitionMixin<ConceptDefMutable>
     virtual const NamespaceDef *getNamespaceDef() const;
     virtual const FileDef *getFileDef() const;
     virtual QCString title() const;
+    virtual int groupId() const;
 
     //---------- ConceptDefMutable
     virtual void setIncludeFile(FileDef *fd,const QCString &incName,bool local,bool force);
@@ -64,6 +65,7 @@ class ConceptDefImpl : public DefinitionMixin<ConceptDefMutable>
     virtual void writeDocumentation(OutputList &);
     virtual void setInitializer(const QCString &init);
     virtual void findSectionsInDocumentation();
+    virtual void setGroupId(int id);
 
     //---------- Helpers
     void writeBriefDescription(OutputList &) const;
@@ -79,6 +81,7 @@ class ConceptDefImpl : public DefinitionMixin<ConceptDefMutable>
     FileDef                     *m_fileDef = 0;
     ArgumentList                 m_tArgList;
     QCString                     m_initializer;
+    int                          m_groupId = -1;
 };
 
 ConceptDefMutable *createConceptDef(
@@ -134,6 +137,8 @@ class ConceptDefAliasImpl : public DefinitionAliasMixin<ConceptDef>
     virtual void writeDeclarationLink(OutputList &ol,bool &found,
                               const QCString &header,bool localNames) const
     { getCdAlias()->writeDeclarationLink(ol,found,header,localNames); }
+    virtual int groupId() const
+    { return getCdAlias()->groupId(); }
 };
 
 ConceptDef *createConceptDefAlias(const Definition *newScope,const ConceptDef *cd)
@@ -266,11 +271,21 @@ QCString ConceptDefImpl::title() const
   return theTranslator->trConceptReference(displayName());
 }
 
+int ConceptDefImpl::groupId() const
+{
+  return m_groupId;
+}
+
+void ConceptDefImpl::setGroupId(int id)
+{
+  m_groupId = id;
+}
+
 void ConceptDefImpl::writeTagFile(TextStream &tagFile)
 {
   tagFile << "  <compound kind=\"concept\">\n";
   tagFile << "    <name>" << convertToXML(name()) << "</name>\n";
-  tagFile << "    <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>\n";
+  tagFile << "    <filename>" << convertToXML(addHtmlExtensionIfMissing(getOutputFileBase())) << "</filename>\n";
   QCString idStr = id();
   if (!idStr.isEmpty())
   {
@@ -494,13 +509,6 @@ void ConceptDefImpl::writeDocumentation(OutputList &ol)
 
   ol.startContents();
 
-  if (Doxygen::searchIndex)
-  {
-    Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
-    Doxygen::searchIndex->addWord(localName(),TRUE);
-  }
-
-  Doxygen::indexList->addIndexItem(this,0);
   //---------------------------------------- start flexible part -------------------------------
 
   for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Concept))
index 8d40ce5..d055579 100644 (file)
@@ -37,6 +37,7 @@ class ConceptDef : public Definition
     virtual const NamespaceDef *getNamespaceDef() const = 0;
     virtual const FileDef *getFileDef() const = 0;
     virtual QCString title() const = 0;
+    virtual int groupId() const = 0;
 };
 
 class ConceptDefMutable : public DefinitionMutable, public ConceptDef
@@ -50,6 +51,7 @@ class ConceptDefMutable : public DefinitionMutable, public ConceptDef
     virtual void writeDocumentation(OutputList &ol) = 0;
     virtual void setInitializer(const QCString &init) = 0;
     virtual void findSectionsInDocumentation() = 0;
+    virtual void setGroupId(int id) = 0;
 };
 
 ConceptDefMutable *createConceptDef(
index 8436fe3..2de2173 100644 (file)
@@ -33,6 +33,7 @@
 #define Config_getBool(name)   (ConfigValues::instance().name())
 #define Config_getInt(name)    (ConfigValues::instance().name())
 #define Config_getEnum(name)   (ConfigValues::instance().name())
+#define Config_getEnumAsString(name)   (ConfigValues::instance().name##_str())
 #define Config_getList(name)   (ConfigValues::instance().name())
 #define Config_updateString(name,value) (ConfigValues::instance().update_##name(value));
 #define Config_updateBool(name,value)   (ConfigValues::instance().update_##name(value));
@@ -82,8 +83,12 @@ namespace Config
 
   /*! Check the validity of the parsed options and correct or warn the user where needed.
    * \param quiet setting for the QUIET option (can have been overruled by means of a command line option)
+   * \param check check  HTML / LaTeX header file etc. on existence (and terminate when not present)
    */
-  void checkAndCorrect(bool quiet);
+  void checkAndCorrect(bool quiet, const bool check);
+
+  /*! Adjust any configuration values based on the value of obsolete options. */
+  void updateObsolete();
 
   /*! Clean up any data */
   void deinit();
index cd19d72..92de131 100644 (file)
@@ -45,8 +45,13 @@ the <code>+=</code> operator can be used instead of <code>=</code> to append
 new values to the list. Values are sequences of non-blanks. If the value should
 contain one or more blanks it must be surrounded by quotes (<code>&quot;...&quot;</code>).
 Multiple lines can be concatenated by inserting a backslash (\c \\)
-as the last character of a line. Environment variables can be expanded
-using the pattern <code>\$(ENV_VARIABLE_NAME)</code>.
+as the last character of a line.
+
+Environment variables can be expanded using the pattern <code>\$(ENV_VARIABLE_NAME)</code>.
+A small example:
+\verbatim
+DOT_PATH      = $(YOUR_DOT_PATH)
+\endverbatim
 
 You can also include part of a configuration file from another configuration
 file using a <code>\@INCLUDE</code> tag as follows:
@@ -430,7 +435,6 @@ Go to the <a href="commands.html">next</a> section or return to the
  started.
 ]]>
       </docs>
-      <value name=''/>
     </option>
     <option type='list' id='STRIP_FROM_INC_PATH' format='string'>
       <docs>
@@ -1375,7 +1379,10 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
 <![CDATA[
  The \c WARN_LOGFILE tag can be used to specify a file to which warning
  and error messages should be written. If left blank the output is written
- to standard error (`stderr`).
+ to standard error (`stderr`). In case the file specified cannot be opened for
+ writing the warning and error messages are written to standard error. When as 
+ file `-` is specified the warning and error messages are written to standard output
+ (`stdout`).
 ]]>
       </docs>
     </option>
@@ -1394,7 +1401,6 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
  \note If this tag is empty the current directory is searched.
 ]]>
       </docs>
-      <value name=''/>
     </option>
     <option type='string' id='INPUT_ENCODING' format='string' defval='UTF-8'>
       <docs>
@@ -1514,7 +1520,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
  (namespaces, classes, functions, etc.) that should be excluded from the
  output. The symbol name can be a fully qualified name, a word, or if the
  wildcard `*` is used, a substring. Examples: `ANamespace`, `AClass`,
- `AClass::ANamespace`, `ANamespace::*Test`
+ `ANamespace::AClass`, `ANamespace::*Test`
  <br>Note that the wildcards are matched against the file with absolute path,
  so to exclude all test directories use the pattern
  `*``/test/``*`
@@ -2161,6 +2167,16 @@ hr.footer {
 ]]>
       </docs>
     </option>
+    <option type='string' id='DOCSET_FEEDURL' format='string' depends='GENERATE_DOCSET'>
+      <docs>
+<![CDATA[
+ This tag determines the URL of the docset
+ feed. A documentation feed provides an umbrella under which multiple
+ documentation sets from a single provider (such as a company or product suite)
+ can be grouped.
+]]>
+      </docs>
+    </option>
     <option type='string' id='DOCSET_BUNDLE_ID' format='string' defval='org.doxygen.Project' depends='GENERATE_DOCSET'>
       <docs>
 <![CDATA[
@@ -2406,14 +2422,16 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
     <option type='bool' id='FULL_SIDEBAR' defval='0' depends='GENERATE_HTML'>
       <docs>
 <![CDATA[
-  When both \c GENERATE_TREEVIEW and \c DISABLE_INDEX are set to YES, then the
+  When both \ref cfg_generate_treeview "GENERATE_TREEVIEW" and \ref cfg_disable_index "DISABLE_INDEX"
+  are set to \c YES, then the
   \c FULL_SIDEBAR option determines if the side bar is limited to only the
   treeview area (value \c NO) or if it should extend to the full height of the
   window (value \c YES). Setting this to \c YES gives a layout similar to
   https://docs.readthedocs.io with more room for contents,
   but less room for the project logo, title, and description.
 
-  If either \c GENERATOR_TREEVIEW or \c DISABLE_INDEX is set to \c NO, this option
+  If either \ref cfg_generate_treeview "GENERATE_TREEVIEW" or \ref cfg_disable_index "DISABLE_INDEX"
+  is set to \c NO, this option
   has no effect.
 ]]>
       </docs>
@@ -2445,6 +2463,14 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
 ]]>
       </docs>
     </option>
+    <option type='bool' id='OBFUSCATE_EMAILS' defval='1' depends='GENERATE_HTML'>
+      <docs>
+<![CDATA[
+If the \c OBFUSCATE_EMAILS tag is set to \c YES, doxygen will
+obfuscate email addresses.
+]]>
+      </docs>
+    </option>
     <option type='enum' id='HTML_FORMULA_FORMAT' defval='png' depends='GENERATE_HTML'>
       <docs>
 <![CDATA[
@@ -2859,7 +2885,7 @@ doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
            as set by \ref cfg_latex_bib_style "LATEX_BIB_STYLE", in case nothing is set the bib style
            `plain` is used.
            This setting is typically used in combination with the block name `CITATIONS_PRESENT`.
- <dt><code>$latexbibfiles</code><dd>will be replaced by the comma separated list of `bib. files
+ <dt><code>$latexbibfiles</code><dd>will be replaced by the comma separated list of `bib`. files
            as set by \ref cfg_cite_bib_files "CITE_BIB_FILES" (when necessary a missing `.bib` is
            automatically added).
            This setting is typically used in combination with the block name `CITATIONS_PRESENT`.
@@ -3489,17 +3515,6 @@ where `loc1` and `loc2` can be relative or absolute paths or URLs.
     </option>
   </group>
   <group name='Dot' docs='Configuration options related to the dot tool'>
-    <option type='bool' id='CLASS_DIAGRAMS' defval='1'>
-      <docs>
-<![CDATA[
- If the \c CLASS_DIAGRAMS tag is set to \c YES, doxygen will
- generate a class diagram (in HTML and \f$\mbox{\LaTeX}\f$) for classes with base or
- super classes. Setting the tag to \c NO turns the diagrams off. Note that
- this option also works with \ref cfg_have_dot "HAVE_DOT" disabled, but it is recommended to
- install and use \c dot, since it yields more powerful graphs.
-]]>
-      </docs>
-    </option>
     <option type='string' id='DIA_PATH' format='dir' defval=''>
       <docs>
 <![CDATA[
@@ -3570,15 +3585,21 @@ to be found in the default search path.
 ]]>
       </docs>
     </option>
-    <option type='bool' id='CLASS_GRAPH' defval='1' depends='HAVE_DOT'>
+    <option type='enum' id='CLASS_GRAPH' defval='YES'>
       <docs>
 <![CDATA[
- If the \c CLASS_GRAPH tag is set to \c YES then doxygen
+ If the \c CLASS_GRAPH tag is set to \c YES (or \c GRAPH) then doxygen
  will generate a graph for each documented class showing the direct and
- indirect inheritance relations. Setting this tag to \c YES will force
- the \ref cfg_class_diagrams "CLASS_DIAGRAMS" tag to \c NO.
+ indirect inheritance relations. In case \ref cfg_have_dot "HAVE_DOT" is set as well
+ `dot` will be used to draw the graph, otherwise the built-in generator will be used.
+ If the \c CLASS_GRAPH tag is set to \c TEXT the direct and indirect inheritance relations
+ will be shown as texts / links.
 ]]>
       </docs>
+      <value name="NO" />
+      <value name="YES" />
+      <value name="TEXT" />
+      <value name="GRAPH" />
     </option>
     <option type='bool' id='COLLABORATION_GRAPH' defval='1' depends='HAVE_DOT'>
       <docs>
@@ -3721,6 +3742,14 @@ UML notation for the relationships.
 ]]>
       </docs>
     </option>
+    <option type='int' id='DIR_GRAPH_MAX_DEPTH' minval='1' maxval='25' defval='1' depends='DIRECTORY_GRAPH'>
+      <docs>
+<![CDATA[
+ The \c DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of
+ levels of child directories generated in directory dependency graphs by \c dot.
+]]>
+      </docs>
+    </option>
     <option type='enum' id='DOT_IMAGE_FORMAT' defval='png' depends='HAVE_DOT'>
       <docs>
 <![CDATA[
@@ -3793,11 +3822,12 @@ UML notation for the relationships.
 ]]>
       </docs>
     </option>
-    <option type='string' id='PLANTUML_JAR_PATH' format='dir' defval=''>
+    <option type='string' id='PLANTUML_JAR_PATH' format='filedir' defval=''>
       <docs>
 <![CDATA[
  When using plantuml, the \c PLANTUML_JAR_PATH tag should be used to specify the path where
- java can find the \c plantuml.jar file. If left blank, it is assumed PlantUML is not used or
+ java can find the \c plantuml.jar file or to the filename of \c jar file to be used.
+ If left blank, it is assumed PlantUML is not used or
  called during a preprocessing step. Doxygen will generate a warning when it encounters a
  \ref cmdstartuml "\\startuml" command in this case and will not generate output for the diagram.
 ]]>
@@ -3874,6 +3904,9 @@ UML notation for the relationships.
  If the \c GENERATE_LEGEND tag is set to \c YES doxygen will
  generate a legend page explaining the meaning of the various boxes and
  arrows in the dot generated graphs.
+ \note This tag requires that \ref cfg_uml_look "UML_LOOK" isn't set, i.e. the
+ doxygen internal graphical representation for inheritance and collaboration diagrams
+ is used.
 ]]>
       </docs>
     </option>
@@ -3887,32 +3920,33 @@ This setting is not only used for dot files but also for msc temporary files.
 ]]>
       </docs>
     </option>
-    <option type='obsolete' id='USE_WINDOWS_ENCODING'/>
-    <option type='obsolete' id='DETAILS_AT_TOP'/>
-    <option type='obsolete' id='QTHELP_FILE'/>
-    <option type='obsolete' id='QTHELP_CONFIG'/>
-    <option type='obsolete' id='DOXYGEN2QTHELP_LOC'/>
-    <option type='obsolete' id='MAX_DOT_GRAPH_WIDTH'/>
-    <option type='obsolete' id='MAX_DOT_GRAPH_HEIGHT'/>
-    <option type='obsolete' id='CGI_NAME'/>
-    <option type='obsolete' id='CGI_URL'/>
-    <option type='obsolete' id='DOC_URL'/>
-    <option type='obsolete' id='DOC_ABSPATH'/>
-    <option type='obsolete' id='BIN_ABSPATH'/>
-    <option type='obsolete' id='EXT_DOC_PATHS'/>
-    <option type='obsolete' id='USE_INLINE_TREES'/>
-    <option type='obsolete' id='SHOW_DIRECTORIES'/>
-    <option type='obsolete' id='HTML_ALIGN_MEMBERS'/>
-    <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'/>
-    <option type='obsolete' id='TCL_SUBST'/>
-    <option type='obsolete' id='COLS_IN_ALPHA_INDEX'/>
-    <option type='obsolete' id='OUTPUT_TEXT_DIRECTION'/>
-    <option type='obsolete' id='DOCBOOK_PROGRAMLISTING'/>
-    <option type='obsolete' id='RTF_SOURCE_CODE'/>
-    <option type='obsolete' id='LATEX_SOURCE_CODE'/>
+    <option type='obsolete' orgtype='bool' id='USE_WINDOWS_ENCODING'/>
+    <option type='obsolete' orgtype='bool' id='DETAILS_AT_TOP'/>
+    <option type='obsolete' orgtype='string' id='QTHELP_FILE'/>
+    <option type='obsolete' orgtype='string' id='QTHELP_CONFIG'/>
+    <option type='obsolete' orgtype='string' id='DOXYGEN2QTHELP_LOC'/>
+    <option type='obsolete' orgtype='int' id='MAX_DOT_GRAPH_WIDTH'/>
+    <option type='obsolete' orgtype='int' id='MAX_DOT_GRAPH_HEIGHT'/>
+    <option type='obsolete' orgtype='string' id='CGI_NAME'/>
+    <option type='obsolete' orgtype='string' id='CGI_URL'/>
+    <option type='obsolete' orgtype='string' id='DOC_URL'/>
+    <option type='obsolete' orgtype='string' id='DOC_ABSPATH'/>
+    <option type='obsolete' orgtype='string' id='BIN_ABSPATH'/>
+    <option type='obsolete' orgtype='list' id='EXT_DOC_PATHS'/>
+    <option type='obsolete' orgtype='bool' id='USE_INLINE_TREES'/>
+    <option type='obsolete' orgtype='bool' id='SHOW_DIRECTORIES'/>
+    <option type='obsolete' orgtype='bool' id='HTML_ALIGN_MEMBERS'/>
+    <option type='obsolete' orgtype='int' id='SYMBOL_CACHE_SIZE'/>
+    <option type='obsolete' orgtype='string' id='XML_SCHEMA'/>
+    <option type='obsolete' orgtype='string' id='XML_DTD'/>
+    <option type='obsolete' orgtype='string' id='PERL_PATH'/>
+    <option type='obsolete' orgtype='string' id='MSCGEN_PATH'/>
+    <option type='obsolete' orgtype='list' id='TCL_SUBST'/>
+    <option type='obsolete' orgtype='int' id='COLS_IN_ALPHA_INDEX'/>
+    <option type='obsolete' orgtype='enum' id='OUTPUT_TEXT_DIRECTION'/>
+    <option type='obsolete' orgtype='bool' id='DOCBOOK_PROGRAMLISTING'/>
+    <option type='obsolete' orgtype='bool' id='RTF_SOURCE_CODE'/>
+    <option type='obsolete' orgtype='bool' id='LATEX_SOURCE_CODE'/>
+    <option type='obsolete' orgtype='bool' id='CLASS_DIAGRAMS'/>
   </group>
 </doxygenconfig>
index b7736c4..66bebce 100755 (executable)
@@ -19,821 +19,878 @@ import textwrap
 from xml.dom import minidom, Node
 
 def transformDocs(doc):
-       # join lines, unless it is an empty line
-       # remove doxygen layout constructs
+    # join lines, unless it is an empty line
+    # remove doxygen layout constructs
         # Note: also look at expert.cpp of doxywizard for doxywizard parts
-       doc = doc.strip()
-       doc = doc.replace("\n", " ")
-       doc = doc.replace("\r", " ")
-       doc = doc.replace("\t", " ")
-       doc = doc.replace("\\&", "&")
-       doc = doc.replace("(\\c ", "(")
-       doc = doc.replace("\\c ", " ")
-       doc = doc.replace("\\b ", " ")
-       doc = doc.replace("\\e ", " ")
-       doc = doc.replace("\\$", "$")
-       doc = doc.replace("\\#include ", "#include ")
-       doc = doc.replace("\\#undef ", "#undef ")
-       doc = doc.replace("-# ", "\n - ")
-       doc = doc.replace(" - ", "\n - ")
-       doc = doc.replace("\\sa", "\nSee also: ")
-       doc = doc.replace("\\par", "\n")
-       doc = doc.replace("@note", "\nNote:")
-       doc = doc.replace("\\note", "\nNote:")
-       doc = doc.replace("\\verbatim", "\n")
-       doc = doc.replace("\\endverbatim", "\n")
-       doc = doc.replace("<code>", "")
-       doc = doc.replace("</code>", "")
-       doc = doc.replace("`", "")
-       doc = doc.replace("\\<", "<")
-       doc = doc.replace("\\>", ">")
-       doc = doc.replace("\\@", "@")
-       doc = doc.replace("\\\\", "\\")
-       # \ref name "description" -> description
-       doc = re.sub('\\\\ref +[^ ]* +"([^"]*)"', '\\1', doc)
-       # \ref specials
-       # \ref <key> -> description
-       doc = re.sub('\\\\ref +doxygen_usage', '"Doxygen usage"', doc)
-       doc = re.sub('\\\\ref +extsearch', '"External Indexing and Searching"',
-                                doc)
-       doc = re.sub('\\\\ref +layout', '"Changing the layout of pages"', doc)
-       doc = re.sub('\\\\ref +external', '"Linking to external documentation"',
-                                doc)
-       doc = re.sub('\\\\ref +doxygen_finetune', '"Fine-tuning the output"',
-                                doc)
-       doc = re.sub('\\\\ref +formulas', '"Including formulas"', doc)
-       # fallback for not handled
-       doc = re.sub('\\\\ref', '', doc)
-       #<a href="address">description</a> -> description (see: address)
-       doc = re.sub('<a +href="([^"]*)" *>([^<]*)</a>', '\\2 (see: \n\\1)', doc)
-       # LaTeX name as formula -> LaTeX
-       doc = doc.replace("\\f$\\mbox{\\LaTeX}\\f$", "LaTeX")
-       # Other formula's (now just 2) so explicitly mentioned.
-       doc = doc.replace("\\f$2^{(16+\\mbox{LOOKUP\\_CACHE\\_SIZE})}\\f$",
-                                         "2^(16+LOOKUP_CACHE_SIZE)")
-       doc = doc.replace("\\f$2^{16} = 65536\\f$", "2^16=65536")
-       # remove consecutive spaces
-       doc = re.sub(" +", " ", doc)
-       # a dirty trick to get an extra empty line in Doxyfile documentation.
-       # <br> will be removed later on again, we need it here otherwise splitlines
-       # will filter the extra line.
-       doc = doc.replace("<br>", "\n<br>\n")
-       # a dirty trick to go to the next line in Doxyfile documentation.
-       # <br/> will be removed later on again, we need it here otherwise splitlines
-       # will filter the line break.
-       doc = doc.replace("<br/>", "\n<br/>\n")
-       #
-       doc = doc.splitlines()
-       split_doc = []
-       for line in doc:
-               split_doc += textwrap.wrap(line, 78)
-       # replace \ by \\, replace " by \", and '  ' by a newline with end string
-       # and start string at next line
-       docC = []
-       for line in split_doc:
-               if (line.strip() != "<br/>"):
-                       docC.append(line.strip().replace('\\', '\\\\').
-                                       replace('"', '\\"').replace("<br>", ""))
-       return docC
+    doc = doc.strip()
+    doc = doc.replace("\n", " ")
+    doc = doc.replace("\r", " ")
+    doc = doc.replace("\t", " ")
+    doc = doc.replace("\\&", "&")
+    doc = doc.replace("(\\c ", "(")
+    doc = doc.replace("\\c ", " ")
+    doc = doc.replace("\\b ", " ")
+    doc = doc.replace("\\e ", " ")
+    doc = doc.replace("\\$", "$")
+    doc = doc.replace("\\#include ", "#include ")
+    doc = doc.replace("\\#undef ", "#undef ")
+    doc = doc.replace("-# ", "\n - ")
+    doc = doc.replace(" - ", "\n - ")
+    doc = doc.replace("\\sa", "\nSee also: ")
+    doc = doc.replace("\\par", "\n")
+    doc = doc.replace("@note", "\nNote:")
+    doc = doc.replace("\\note", "\nNote:")
+    doc = doc.replace("\\verbatim", "\n")
+    doc = doc.replace("\\endverbatim", "\n")
+    doc = doc.replace("<code>", "")
+    doc = doc.replace("</code>", "")
+    doc = doc.replace("`", "")
+    doc = doc.replace("\\<", "<")
+    doc = doc.replace("\\>", ">")
+    doc = doc.replace("\\@", "@")
+    doc = doc.replace("\\\\", "\\")
+    # \ref name "description" -> description
+    doc = re.sub('\\\\ref +[^ ]* +"([^"]*)"', '\\1', doc)
+    # \ref specials
+    # \ref <key> -> description
+    doc = re.sub('\\\\ref +doxygen_usage', '"Doxygen usage"', doc)
+    doc = re.sub('\\\\ref +extsearch', '"External Indexing and Searching"',
+                 doc)
+    doc = re.sub('\\\\ref +layout', '"Changing the layout of pages"', doc)
+    doc = re.sub('\\\\ref +external', '"Linking to external documentation"',
+                 doc)
+    doc = re.sub('\\\\ref +doxygen_finetune', '"Fine-tuning the output"',
+                 doc)
+    doc = re.sub('\\\\ref +formulas', '"Including formulas"', doc)
+    # fallback for not handled
+    doc = re.sub('\\\\ref', '', doc)
+    #<a href="address">description</a> -> description (see: address)
+    doc = re.sub('<a +href="([^"]*)" *>([^<]*)</a>', '\\2 (see: \n\\1)', doc)
+    # LaTeX name as formula -> LaTeX
+    doc = doc.replace("\\f$\\mbox{\\LaTeX}\\f$", "LaTeX")
+    # Other formula's (now just 2) so explicitly mentioned.
+    doc = doc.replace("\\f$2^{(16+\\mbox{LOOKUP\\_CACHE\\_SIZE})}\\f$",
+                      "2^(16+LOOKUP_CACHE_SIZE)")
+    doc = doc.replace("\\f$2^{16} = 65536\\f$", "2^16=65536")
+    # remove consecutive spaces
+    doc = re.sub(" +", " ", doc)
+    # a dirty trick to get an extra empty line in Doxyfile documentation.
+    # <br> will be removed later on again, we need it here otherwise splitlines
+    # will filter the extra line.
+    doc = doc.replace("<br>", "\n<br>\n")
+    # a dirty trick to go to the next line in Doxyfile documentation.
+    # <br/> will be removed later on again, we need it here otherwise splitlines
+    # will filter the line break.
+    doc = doc.replace("<br/>", "\n<br/>\n")
+    #
+    doc = doc.splitlines()
+    split_doc = []
+    for line in doc:
+        split_doc += textwrap.wrap(line, 78)
+    # replace \ by \\, replace " by \", and '  ' by a newline with end string
+    # and start string at next line
+    docC = []
+    for line in split_doc:
+        if (line.strip() != "<br/>"):
+            docC.append(line.strip().replace('\\', '\\\\').
+                    replace('"', '\\"').replace("<br>", ""))
+    return docC
 
 
 def collectValues(node):
-       values = []
-       for n in node.childNodes:
-               if (n.nodeName == "value"):
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if n.getAttribute('name') != "":
-                                       if n.getAttribute('show_docu') != "NO":
-                                               name = "<code>" + n.getAttribute('name') + "</code>"
-                                               desc = n.getAttribute('desc')
-                                               if (desc != ""):
-                                                       name += " " + desc
-                                               values.append(name)
-       return values
+    values = []
+    for n in node.childNodes:
+        if (n.nodeName == "value"):
+            if n.nodeType == Node.ELEMENT_NODE:
+                if n.getAttribute('name') != "":
+                    if n.getAttribute('show_docu') != "NO":
+                        name = "<code>" + n.getAttribute('name') + "</code>"
+                        desc = n.getAttribute('desc')
+                        if (desc != ""):
+                            name += " " + desc
+                        values.append(name)
+    return values
 
 
 def addValues(var, node):
-       for n in node.childNodes:
-               if (n.nodeName == "value"):
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               name = n.getAttribute('name')
-                               print("  %s->addValue(\"%s\");" % (var, name))
+    for n in node.childNodes:
+        if (n.nodeName == "value"):
+            if n.nodeType == Node.ELEMENT_NODE:
+                name = n.getAttribute('name')
+                print("  %s->addValue(\"%s\");" % (var, name))
 
 
 def parseHeader(node,objName):
-       doc = ""
-       for n in node.childNodes:
-               if n.nodeType == Node.ELEMENT_NODE:
-                       if (n.nodeName == "docs"):
-                               if (n.getAttribute('doxyfile') != "0"):
-                                       doc += parseDocs(n)
-       docC = transformDocs(doc)
-       print("  %s->setHeader(" % (objName))
-       rng = len(docC)
-       for i in range(rng):
-               line = docC[i]
-               if i != rng - 1:  # since we go from 0 to rng-1
-                       print("              \"%s\\n\"" % (line))
-               else:
-                       print("              \"%s\"" % (line))
-       print("             );")
+    doc = ""
+    for n in node.childNodes:
+        if n.nodeType == Node.ELEMENT_NODE:
+            if (n.nodeName == "docs"):
+                if (n.getAttribute('doxyfile') != "0"):
+                    doc += parseDocs(n)
+    docC = transformDocs(doc)
+    print("  %s->setHeader(" % (objName))
+    rng = len(docC)
+    for i in range(rng):
+        line = docC[i]
+        if i != rng - 1:  # since we go from 0 to rng-1
+            print("              \"%s\\n\"" % (line))
+        else:
+            print("              \"%s\"" % (line))
+    print("             );")
 
 
 def prepCDocs(node):
-       type = node.getAttribute('type')
-       format = node.getAttribute('format')
-       defval = node.getAttribute('defval')
-       adefval = node.getAttribute('altdefval')
-       doc = "";
-       if (type != 'obsolete'):
-               for n in node.childNodes:
-                       if (n.nodeName == "docs"):
-                               if (n.getAttribute('doxyfile') != "0"):
-                                       if n.nodeType == Node.ELEMENT_NODE:
-                                               doc += parseDocs(n)
-               if (type == 'enum'):
-                       values = collectValues(node)
-                       doc += "<br/>Possible values are: "
-                       rng = len(values)
-                       for i in range(rng):
-                               val = values[i]
-                               if i == rng - 2:
-                                       doc += "%s and " % (val)
-                               elif i == rng - 1:
-                                       doc += "%s." % (val)
-                               else:
-                                       doc += "%s, " % (val)
-                       if (defval != ""):
-                               doc += "<br/>The default value is: <code>%s</code>." % (defval)
-               elif (type == 'int'):
-                       minval = node.getAttribute('minval')
-                       maxval = node.getAttribute('maxval')
-                       doc += "<br/>%s: %s, %s: %s, %s: %s." % (" Minimum value", minval, 
-                                        "maximum value", maxval,
-                                        "default value", defval)
-               elif (type == 'bool'):
-                       if (node.hasAttribute('altdefval')):
-                         doc += "<br/>%s: %s." % ("The default value is", "system dependent")
-                       else:
-                         doc += "<br/>%s: %s." % ("The default value is", "YES" if (defval == "1") else "NO")
-               elif (type == 'list'):
-                       if format == 'string':
-                               values = collectValues(node)
-                               rng = len(values)
-                               for i in range(rng):
-                                       val = values[i]
-                                       if i == rng - 2:
-                                               doc += "%s and " % (val)
-                                       elif i == rng - 1:
-                                               doc += "%s." % (val)
-                                       else:
-                                               doc += "%s, " % (val)
-               elif (type == 'string'):
-                       if format == 'dir':
-                               if defval != '':
-                                       doc += "<br/>The default directory is: <code>%s</code>." % (
-                                               defval)
-                       elif format == 'file':
-                               abspath = node.getAttribute('abspath')
-                               if defval != '':
-                                       if abspath != '1':
-                                               doc += "<br/>The default file is: <code>%s</code>." % (
-                                                       defval)
-                                       else:
-                                               doc += "<br/>%s: %s%s%s." % (
-                                                       "The default file (with absolute path) is",
-                                                       "<code>",defval,"</code>")
-                               else:
-                                       if abspath == '1':
-                                               doc += "<br/>The file has to be specified with full path."
-                       elif format =='image':
-                               abspath = node.getAttribute('abspath')
-                               if defval != '':
-                                       if abspath != '1':
-                                               doc += "<br/>The default image is: <code>%s</code>." % (
-                                                       defval)
-                                       else:
-                                               doc += "<br/>%s: %s%s%s." % (
-                                                       "The default image (with absolute path) is",
-                                                       "<code>",defval,"</code>")
-                               else:
-                                       if abspath == '1':
-                                               doc += "<br/>The image has to be specified with full path."
-                       else: # format == 'string':
-                               if defval != '':
-                                       doc += "<br/>The default value is: <code>%s</code>." % (
-                                               defval)
-               # depends handling
-               if (node.hasAttribute('depends')):
-                       depends = node.getAttribute('depends')
-                       doc += "<br/>%s \\ref cfg_%s \"%s\" is set to \\c YES." % (
-                               "This tag requires that the tag", depends.lower(), depends.upper())
-
-       docC = transformDocs(doc)
-       return docC;
+    type = node.getAttribute('type')
+    format = node.getAttribute('format')
+    defval = node.getAttribute('defval')
+    adefval = node.getAttribute('altdefval')
+    doc = "";
+    if (type != 'obsolete'):
+        for n in node.childNodes:
+            if (n.nodeName == "docs"):
+                if (n.getAttribute('doxyfile') != "0"):
+                    if n.nodeType == Node.ELEMENT_NODE:
+                        doc += parseDocs(n)
+        if (type == 'enum'):
+            values = collectValues(node)
+            doc += "<br/>Possible values are: "
+            rng = len(values)
+            for i in range(rng):
+                val = values[i]
+                if i == rng - 2:
+                    doc += "%s and " % (val)
+                elif i == rng - 1:
+                    doc += "%s." % (val)
+                else:
+                    doc += "%s, " % (val)
+            if (defval != ""):
+                doc += "<br/>The default value is: <code>%s</code>." % (defval)
+        elif (type == 'int'):
+            minval = node.getAttribute('minval')
+            maxval = node.getAttribute('maxval')
+            doc += "<br/>%s: %s, %s: %s, %s: %s." % (" Minimum value", minval, 
+                     "maximum value", maxval,
+                     "default value", defval)
+        elif (type == 'bool'):
+            if (node.hasAttribute('altdefval')):
+              doc += "<br/>%s: %s." % ("The default value is", "system dependent")
+            else:
+              doc += "<br/>%s: %s." % ("The default value is", "YES" if (defval == "1") else "NO")
+        elif (type == 'list'):
+            if format == 'string':
+                values = collectValues(node)
+                rng = len(values)
+                for i in range(rng):
+                    val = values[i]
+                    if i == rng - 2:
+                        doc += "%s and " % (val)
+                    elif i == rng - 1:
+                        doc += "%s." % (val)
+                    else:
+                        doc += "%s, " % (val)
+        elif (type == 'string'):
+            if format == 'dir':
+                if defval != '':
+                    doc += "<br/>The default directory is: <code>%s</code>." % (
+                        defval)
+            elif format == 'file':
+                abspath = node.getAttribute('abspath')
+                if defval != '':
+                    if abspath != '1':
+                        doc += "<br/>The default file is: <code>%s</code>." % (
+                            defval)
+                    else:
+                        doc += "<br/>%s: %s%s%s." % (
+                            "The default file (with absolute path) is",
+                            "<code>",defval,"</code>")
+                else:
+                    if abspath == '1':
+                        doc += "<br/>The file has to be specified with full path."
+            elif format =='image':
+                abspath = node.getAttribute('abspath')
+                if defval != '':
+                    if abspath != '1':
+                        doc += "<br/>The default image is: <code>%s</code>." % (
+                            defval)
+                    else:
+                        doc += "<br/>%s: %s%s%s." % (
+                            "The default image (with absolute path) is",
+                            "<code>",defval,"</code>")
+                else:
+                    if abspath == '1':
+                        doc += "<br/>The image has to be specified with full path."
+            else: # format == 'string':
+                if defval != '':
+                    doc += "<br/>The default value is: <code>%s</code>." % (
+                        defval)
+        # depends handling
+        if (node.hasAttribute('depends')):
+            depends = node.getAttribute('depends')
+            doc += "<br/>%s \\ref cfg_%s \"%s\" is set to \\c YES." % (
+                "This tag requires that the tag", depends.lower(), depends.upper())
+
+    docC = transformDocs(doc)
+    return docC;
 
 def parseOption(node):
-       # Handling part for Doxyfile
-       name = node.getAttribute('id')
-       type = node.getAttribute('type')
-       format = node.getAttribute('format')
-       defval = node.getAttribute('defval')
-       adefval = node.getAttribute('altdefval')
-       depends = node.getAttribute('depends')
-       setting = node.getAttribute('setting')
-       docC = prepCDocs(node);
-       if len(setting) > 0:
-               print("#if %s" % (setting))
-       print("  //----")
-       if type == 'bool':
-               if len(adefval) > 0:
-                       enabled = adefval
-               elif defval == '1':
-                       enabled = "TRUE"
-               else:
-                       enabled = "FALSE"
-               print("  cb = cfg->addBool(")
-               print("             \"%s\"," % (name))
-               rng = len(docC)
-               for i in range(rng):
-                       line = docC[i]
-                       if i != rng - 1:  # since we go from 0 to rng-1
-                               print("              \"%s\\n\"" % (line))
-                       else:
-                               print("              \"%s\"," % (line))
-               print("              %s" % (enabled))
-               print("             );")
-               if depends != '':
-                       print("  cb->addDependency(\"%s\");" % (depends))
-       elif type == 'string':
-               print("  cs = cfg->addString(")
-               print("              \"%s\"," % (name))
-               rng = len(docC)
-               for i in range(rng):
-                       line = docC[i]
-                       if i != rng - 1:  # since we go from 0 to rng-1
-                               print("              \"%s\\n\"" % (line))
-                       else:
-                               print("              \"%s\"" % (line))
-               print("             );")
-               if defval != '':
-                       print("  cs->setDefaultValue(\"%s\");" % (defval.replace('\\','\\\\')))
-               if format == 'file':
-                       print("  cs->setWidgetType(ConfigString::File);")
-               elif format == 'image':
-                       print("  cs->setWidgetType(ConfigString::Image);")
-               elif format == 'dir':
-                       print("  cs->setWidgetType(ConfigString::Dir);")
-               if depends != '':
-                       print("  cs->addDependency(\"%s\");" % (depends))
-       elif type == 'enum':
-               print("  ce = cfg->addEnum(")
-               print("              \"%s\"," % (name))
-               rng = len(docC)
-               for i in range(rng):
-                       line = docC[i]
-                       if i != rng - 1:  # since we go from 0 to rng-1
-                               print("              \"%s\\n\"" % (line))
-                       else:
-                               print("              \"%s\"," % (line))
-               print("              \"%s\"" % (defval))
-               print("             );")
-               addValues("ce", node)
-               if depends != '':
-                       print("  ce->addDependency(\"%s\");" % (depends))
-       elif type == 'int':
-               minval = node.getAttribute('minval')
-               maxval = node.getAttribute('maxval')
-               print("  ci = cfg->addInt(")
-               print("              \"%s\"," % (name))
-               rng = len(docC)
-               for i in range(rng):
-                       line = docC[i]
-                       if i != rng - 1:  # since we go from 0 to rng-1
-                               print("              \"%s\\n\"" % (line))
-                       else:
-                               print("              \"%s\"," % (line))
-               print("              %s,%s,%s" % (minval, maxval, defval))
-               print("             );")
-               if depends != '':
-                       print("  ci->addDependency(\"%s\");" % (depends))
-       elif type == 'list':
-               print("  cl = cfg->addList(")
-               print("              \"%s\"," % (name))
-               rng = len(docC)
-               for i in range(rng):
-                       line = docC[i]
-                       if i != rng - 1:  # since we go from 0 to rng-1
-                               print("              \"%s\\n\"" % (line))
-                       else:
-                               print("              \"%s\"" % (line))
-               print("             );")
-               addValues("cl", node)
-               if depends != '':
-                       print("  cl->addDependency(\"%s\");" % (depends))
-               if format == 'file':
-                       print("  cl->setWidgetType(ConfigList::File);")
-               elif format == 'dir':
-                       print("  cl->setWidgetType(ConfigList::Dir);")
-               elif format == 'filedir':
-                       print("  cl->setWidgetType(ConfigList::FileAndDir);")
-       elif type == 'obsolete':
-               print("  cfg->addObsolete(\"%s\");" % (name))
-       if len(setting) > 0:
-               print("#else")
-               print("  cfg->addDisabled(\"%s\");" % (name))
-               print("#endif")
+    # Handling part for Doxyfile
+    name = node.getAttribute('id')
+    type = node.getAttribute('type')
+    format = node.getAttribute('format')
+    defval = node.getAttribute('defval')
+    adefval = node.getAttribute('altdefval')
+    depends = node.getAttribute('depends')
+    setting = node.getAttribute('setting')
+    orgtype = node.getAttribute('orgtype')
+    docC = prepCDocs(node);
+    if len(setting) > 0:
+        print("#if %s" % (setting))
+    print("  //----")
+    if type == 'bool':
+        if len(adefval) > 0:
+            enabled = adefval
+        elif defval == '1':
+            enabled = "TRUE"
+        else:
+            enabled = "FALSE"
+        print("  cb = cfg->addBool(")
+        print("             \"%s\"," % (name))
+        rng = len(docC)
+        for i in range(rng):
+            line = docC[i]
+            if i != rng - 1:  # since we go from 0 to rng-1
+                print("              \"%s\\n\"" % (line))
+            else:
+                print("              \"%s\"," % (line))
+        print("              %s" % (enabled))
+        print("             );")
+        if depends != '':
+            print("  cb->addDependency(\"%s\");" % (depends))
+    elif type == 'string':
+        print("  cs = cfg->addString(")
+        print("              \"%s\"," % (name))
+        rng = len(docC)
+        for i in range(rng):
+            line = docC[i]
+            if i != rng - 1:  # since we go from 0 to rng-1
+                print("              \"%s\\n\"" % (line))
+            else:
+                print("              \"%s\"" % (line))
+        print("             );")
+        if defval != '':
+            print("  cs->setDefaultValue(\"%s\");" % (defval.replace('\\','\\\\')))
+        if format == 'file':
+            print("  cs->setWidgetType(ConfigString::File);")
+        elif format == 'image':
+            print("  cs->setWidgetType(ConfigString::Image);")
+        elif format == 'dir':
+            print("  cs->setWidgetType(ConfigString::Dir);")
+        elif format == 'filedir':
+            print("  cs->setWidgetType(ConfigString::FileAndDir);")
+        if depends != '':
+            print("  cs->addDependency(\"%s\");" % (depends))
+    elif type == 'enum':
+        print("  ce = cfg->addEnum(")
+        print("              \"%s\"," % (name))
+        rng = len(docC)
+        for i in range(rng):
+            line = docC[i]
+            if i != rng - 1:  # since we go from 0 to rng-1
+                print("              \"%s\\n\"" % (line))
+            else:
+                print("              \"%s\"," % (line))
+        print("              \"%s\"" % (defval))
+        print("             );")
+        addValues("ce", node)
+        if depends != '':
+            print("  ce->addDependency(\"%s\");" % (depends))
+    elif type == 'int':
+        minval = node.getAttribute('minval')
+        maxval = node.getAttribute('maxval')
+        print("  ci = cfg->addInt(")
+        print("              \"%s\"," % (name))
+        rng = len(docC)
+        for i in range(rng):
+            line = docC[i]
+            if i != rng - 1:  # since we go from 0 to rng-1
+                print("              \"%s\\n\"" % (line))
+            else:
+                print("              \"%s\"," % (line))
+        print("              %s,%s,%s" % (minval, maxval, defval))
+        print("             );")
+        if depends != '':
+            print("  ci->addDependency(\"%s\");" % (depends))
+    elif type == 'list':
+        print("  cl = cfg->addList(")
+        print("              \"%s\"," % (name))
+        rng = len(docC)
+        for i in range(rng):
+            line = docC[i]
+            if i != rng - 1:  # since we go from 0 to rng-1
+                print("              \"%s\\n\"" % (line))
+            else:
+                print("              \"%s\"" % (line))
+        print("             );")
+        addValues("cl", node)
+        if depends != '':
+            print("  cl->addDependency(\"%s\");" % (depends))
+        if format == 'file':
+            print("  cl->setWidgetType(ConfigList::File);")
+        elif format == 'dir':
+            print("  cl->setWidgetType(ConfigList::Dir);")
+        elif format == 'filedir':
+            print("  cl->setWidgetType(ConfigList::FileAndDir);")
+    elif type == 'obsolete':
+        print("  cfg->addObsolete(\"%s\",ConfigOption::O_%s);" % (name,orgtype.capitalize()))
+    if len(setting) > 0:
+        print("#else")
+        print("  cfg->addDisabled(\"%s\");" % (name))
+        print("#endif")
 
 
 def parseGroups(node):
-       name = node.getAttribute('name')
-       doc = node.getAttribute('docs')
-       setting = node.getAttribute('setting')
-       if len(setting) > 0:
-               print("#if %s" % (setting))
-       print("%s%s" % ("  //-----------------------------------------",
-                                       "----------------------------------"))
-       print("  cfg->addInfo(\"%s\",\"%s\");" % (name, doc))
-       print("%s%s" % ("  //-----------------------------------------",
-                                       "----------------------------------"))
-       print("")
-       for n in node.childNodes:
-               if n.nodeType == Node.ELEMENT_NODE:
-                       parseOption(n)
-       if len(setting) > 0:
-               print("#endif")
-
+    name = node.getAttribute('name')
+    doc = node.getAttribute('docs')
+    setting = node.getAttribute('setting')
+    if len(setting) > 0:
+        print("#if %s" % (setting))
+    print("%s%s" % ("  //-----------------------------------------",
+                    "----------------------------------"))
+    print("  cfg->addInfo(\"%s\",\"%s\");" % (name, doc))
+    print("%s%s" % ("  //-----------------------------------------",
+                    "----------------------------------"))
+    if len(setting) > 0:
+        print("#endif")
+    print("")
+    for n in node.childNodes:
+        if n.nodeType == Node.ELEMENT_NODE:
+            parseOption(n)
+
+def parseGroupMapEnums(node):
+    def escape(value):
+        return re.sub(r'[^\w]','_',value)
+    for n in node.childNodes:
+        if n.nodeType == Node.ELEMENT_NODE:
+            type   = n.getAttribute('type')
+            name   = n.getAttribute('id')
+            defval = n.getAttribute('defval')
+            if type=='enum':
+                print("\nenum class %s_t" % (name))
+                print("{")
+                for nv in n.childNodes:
+                    if nv.nodeName == "value":
+                        value = nv.getAttribute('name')
+                        if value:
+                            print("  %s," % (escape(value)))
+                print("};\n")
+                print("inline {0}_t {1}_str2enum(const QCString &s)".format(name,name))
+                print("{")
+                print("  QCString lc = s.lower();")
+                print("  static const std::unordered_map<std::string,{0}_t> map =".format(name))
+                print("  {")
+                for nv in n.childNodes:
+                    if nv.nodeName == "value":
+                        value = nv.getAttribute('name')
+                        if value:
+                            print("    {{ \"{0}\", {1}_t::{2} }},".format(value.lower(),name,escape(value)))
+                print("  };")
+                print("  auto it = map.find(lc.str());")
+                print("  return it!=map.end() ? it->second : {0}_t::{1};".format(name,escape(defval)))
+                print("}\n")
+                print("inline QCString {0}_enum2str({1}_t v)".format(name,name))
+                print("{")
+                print("  switch(v)")
+                print("  {")
+                for nv in n.childNodes:
+                    if nv.nodeName == "value":
+                        value = nv.getAttribute('name')
+                        if value:
+                            print("    case {0}_t::{1}: return \"{2}\";".format(name,escape(value),value))
+                print("  }")
+                print("  return \"{0}\";".format(defval))
+                print("}")
 
 def parseGroupMapGetter(node):
-       map = { 'bool':'bool', 'string':'const QCString &', 'enum':'const QCString &', 'int':'int', 'list':'const StringVector &' }
-       for n in node.childNodes:
-               if n.nodeType == Node.ELEMENT_NODE:
-                       setting = n.getAttribute('setting')
-                       if len(setting) > 0:
-                               print("#if %s" % (setting))
-                       type = n.getAttribute('type')
-                       name = n.getAttribute('id')
-                       if type in map:
-                               print("    %-20s %-30s const                  { return m_%s; }" % (map[type],name+'()',name))
-                       if len(setting) > 0:
-                               print("#endif")
+    map = { 'bool':'bool', 'string':'const QCString &', 'int':'int', 'list':'const StringVector &' }
+    for n in node.childNodes:
+        if n.nodeType == Node.ELEMENT_NODE:
+            setting = n.getAttribute('setting')
+            if len(setting) > 0:
+                print("#if %s" % (setting))
+            type = n.getAttribute('type')
+            name = n.getAttribute('id')
+            if type=='enum':
+                print("    %-22s %-30s const                  { return %s(m_%s); }" % (name+'_t',name+'()',name+'_str2enum',name))
+                print("    %-22s %-30s const                  { return m_%s; }" % ('const QCString &',name+'_str()',name))
+            elif type in map:
+                print("    %-22s %-30s const                  { return m_%s; }" % (map[type],name+'()',name))
+            if len(setting) > 0:
+                print("#endif")
 
 def parseGroupMapSetter(node):
-       map = { 'bool':'bool', 'string':'const QCString &', 'enum':'const QCString &', 'int':'int', 'list':'const StringVector &' }
-       for n in node.childNodes:
-               if n.nodeType == Node.ELEMENT_NODE:
-                       setting = n.getAttribute('setting')
-                       if len(setting) > 0:
-                               print("#if %s" % (setting))
-                       type = n.getAttribute('type')
-                       name = n.getAttribute('id')
-                       if type in map:
-                               print("    %-20s update_%-46s { m_%s = v; return m_%s; }" % (map[type],name+'('+map[type]+' v)',name,name))
-                       if len(setting) > 0:
-                               print("#endif")
+    map = { 'bool':'bool', 'string':'const QCString &', 'int':'int', 'list':'const StringVector &' }
+    for n in node.childNodes:
+        if n.nodeType == Node.ELEMENT_NODE:
+            setting = n.getAttribute('setting')
+            if len(setting) > 0:
+                print("#if %s" % (setting))
+            type = n.getAttribute('type')
+            name = n.getAttribute('id')
+            if type=='enum':
+                print("    %-22s update_%-46s { m_%s = %s(v); return v; }" % (name+'_t',name+'('+name+'_t '+' v)',name,name+'_enum2str'))
+            elif type in map:
+                print("    %-22s update_%-46s { m_%s = v; return m_%s; }" % (map[type],name+'('+map[type]+' v)',name,name))
+            if len(setting) > 0:
+                print("#endif")
 
 def parseGroupMapVar(node):
-       map = { 'bool':'bool', 'string':'QCString', 'enum':'QCString', 'int':'int', 'list':'StringVector' }
-       for n in node.childNodes:
-               if n.nodeType == Node.ELEMENT_NODE:
-                       setting = n.getAttribute('setting')
-                       if len(setting) > 0:
-                               print("#if %s" % (setting))
-                       type = n.getAttribute('type')
-                       name = n.getAttribute('id')
-                       if type in map:
-                               print("    %-12s m_%s;" % (map[type],name))
-                       if len(setting) > 0:
-                               print("#endif")
+    map = { 'bool':'bool', 'string':'QCString', 'enum':'QCString', 'int':'int', 'list':'StringVector' }
+    for n in node.childNodes:
+        if n.nodeType == Node.ELEMENT_NODE:
+            setting = n.getAttribute('setting')
+            if len(setting) > 0:
+                print("#if %s" % (setting))
+            type = n.getAttribute('type')
+            name = n.getAttribute('id')
+            if type in map:
+                print("    %-12s m_%s;" % (map[type],name))
+            if len(setting) > 0:
+                print("#endif")
 
 def parseGroupInit(node):
-       map = { 'bool':'Bool', 'string':'String', 'enum':'Enum', 'int':'Int', 'list':'List' }
-       for n in node.childNodes:
-               if n.nodeType == Node.ELEMENT_NODE:
-                       setting = n.getAttribute('setting')
-                       if len(setting) > 0:
-                               print("#if %s" % (setting))
-                       type = n.getAttribute('type')
-                       name = n.getAttribute('id')
-                       if type in map:
-                               print("  %-25s = ConfigImpl::instance()->get%s(__FILE__,__LINE__,\"%s\");" % ('m_'+name,map[type],name))
-                       if len(setting) > 0:
-                               print("#endif")
+    map = { 'bool':'Bool', 'string':'String', 'enum':'Enum', 'int':'Int', 'list':'List' }
+    for n in node.childNodes:
+        if n.nodeType == Node.ELEMENT_NODE:
+            setting = n.getAttribute('setting')
+            if len(setting) > 0:
+                print("#if %s" % (setting))
+            type = n.getAttribute('type')
+            name = n.getAttribute('id')
+            if type in map:
+                print("  %-25s = ConfigImpl::instance()->get%s(__FILE__,__LINE__,\"%s\");" % ('m_'+name,map[type],name))
+            if len(setting) > 0:
+                print("#endif")
 
 def parseGroupMapInit(node):
-       map = { 'bool':'Bool', 'string':'String', 'enum':'String', 'int':'Int', 'list':'List' }
-       for n in node.childNodes:
-               if n.nodeType == Node.ELEMENT_NODE:
-                       setting = n.getAttribute('setting')
-                       if len(setting) > 0:
-                               print("#if %s" % (setting))
-                       type = n.getAttribute('type')
-                       name = n.getAttribute('id')
-                       if type in map:
-                               print("    { %-25s Info{ %-13s &ConfigValues::m_%s }}," % ('\"'+name+'\",','Info::'+map[type]+',',name))
-                       if len(setting) > 0:
-                               print("#endif")
+    map = { 'bool':'Bool', 'string':'String', 'enum':'String', 'int':'Int', 'list':'List' }
+    for n in node.childNodes:
+        if n.nodeType == Node.ELEMENT_NODE:
+            setting = n.getAttribute('setting')
+            if len(setting) > 0:
+                print("#if %s" % (setting))
+            type = n.getAttribute('type')
+            name = n.getAttribute('id')
+            if type in map:
+                print("    { %-25s Info{ %-13s &ConfigValues::m_%s }}," % ('\"'+name+'\",','Info::'+map[type]+',',name))
+            if len(setting) > 0:
+                print("#endif")
 
 def parseGroupCDocs(node):
-       for n in node.childNodes:
-               if n.nodeType == Node.ELEMENT_NODE:
-                       type = n.getAttribute('type')
-                       name = n.getAttribute('id')
-                       docC = prepCDocs(n);
-                       if type != 'obsolete':
-                               print("  doc->add(")
-                               print("              \"%s\"," % (name))
-                               rng = len(docC)
-                               for i in range(rng):
-                                       line = docC[i]
-                                       if i != rng - 1:  # since we go from 0 to rng-1
-                                               print("              \"%s\\n\"" % (line))
-                                       else:
-                                               print("              \"%s\"" % (line))
-                               print("          );")
+    for n in node.childNodes:
+        if n.nodeType == Node.ELEMENT_NODE:
+            type = n.getAttribute('type')
+            name = n.getAttribute('id')
+            docC = prepCDocs(n);
+            if type != 'obsolete':
+                print("  doc->add(")
+                print("              \"%s\"," % (name))
+                rng = len(docC)
+                for i in range(rng):
+                    line = docC[i]
+                    if i != rng - 1:  # since we go from 0 to rng-1
+                        print("              \"%s\\n\"" % (line))
+                    else:
+                        print("              \"%s\"" % (line))
+                print("          );")
 
 def parseOptionDoc(node, first):
-       # Handling part for documentation
-       name = node.getAttribute('id')
-       type = node.getAttribute('type')
-       format = node.getAttribute('format')
-       defval = node.getAttribute('defval')
-       adefval = node.getAttribute('altdefval')
-       depends = node.getAttribute('depends')
-       setting = node.getAttribute('setting')
-       doc = ""
-       if (type != 'obsolete'):
-               for n in node.childNodes:
-                       if (n.nodeName == "docs"):
-                               if (n.getAttribute('documentation') != "0"):
-                                       if n.nodeType == Node.ELEMENT_NODE:
-                                               doc += parseDocs(n)
-               if (first):
-                       print(" \\anchor cfg_%s" % (name.lower()))
-                       print("<dl>")
-                       print("")
-                       print("<dt>\\c %s <dd>" % (name))
-               else:
-                       print(" \\anchor cfg_%s" % (name.lower()))
-                       print("<dt>\\c %s <dd>" % (name))
-               print(" \\addindex %s" % (name))
-               print(doc)
-               if (type == 'enum'):
-                       values = collectValues(node)
-                       print("")
-                       print("Possible values are: ")
-                       rng = len(values)
-                       for i in range(rng):
-                               val = values[i]
-                               if i == rng - 2:
-                                       print("%s and " % (val))
-                               elif i == rng - 1:
-                                       print("%s." % (val))
-                               else:
-                                       print("%s, " % (val))
-                       if (defval != ""):
-                               print("")
-                               print("")
-                               print("The default value is: <code>%s</code>." % (defval))
-                       print("")
-               elif (type == 'int'):
-                       minval = node.getAttribute('minval')
-                       maxval = node.getAttribute('maxval')
-                       print("")
-                       print("")
-                       print("%s: %s%s%s, %s: %s%s%s, %s: %s%s%s." % (
-                                        " Minimum value", "<code>", minval, "</code>", 
-                                        "maximum value", "<code>", maxval, "</code>",
-                                        "default value", "<code>", defval, "</code>"))
-                       print("")
-               elif (type == 'bool'):
-                       print("")
-                       print("")
-                       if (node.hasAttribute('altdefval')):
-                               print("The default value is: system dependent.")
-                       else:
-                               print("The default value is: <code>%s</code>." % (
-                                       "YES" if (defval == "1") else "NO"))
-                       print("")
-               elif (type == 'list'):
-                       if format == 'string':
-                               values = collectValues(node)
-                               rng = len(values)
-                               for i in range(rng):
-                                       val = values[i]
-                                       if i == rng - 2:
-                                               print("%s and " % (val))
-                                       elif i == rng - 1:
-                                               print("%s." % (val))
-                                       else:
-                                               print("%s, " % (val))
-                       print("")
-               elif (type == 'string'):
-                       if format == 'dir':
-                               if defval != '':
-                                       print("")
-                                       print("The default directory is: <code>%s</code>." % (
-                                               defval))
-                       elif format == 'file':
-                               abspath = node.getAttribute('abspath')
-                               if defval != '':
-                                       print("")
-                                       if abspath != '1':
-                                               print("The default file is: <code>%s</code>." % (
-                                                       defval))
-                                       else:
-                                               print("%s: %s%s%s." % (
-                                                       "The default file (with absolute path) is",
-                                                       "<code>",defval,"</code>"))
-                               else:
-                                       if abspath == '1':
-                                               print("")
-                                               print("The file has to be specified with full path.")
-                       elif format =='image':
-                               abspath = node.getAttribute('abspath')
-                               if defval != '':
-                                       print("")
-                                       if abspath != '1':
-                                               print("The default image is: <code>%s</code>." % (
-                                                       defval))
-                                       else:
-                                               print("%s: %s%s%s." % (
-                                                       "The default image (with absolute path) is",
-                                                       "<code>",defval,"</code>"))
-                               else:
-                                       if abspath == '1':
-                                               print("")
-                                               print("The image has to be specified with full path.")
-                       else: # format == 'string':
-                               if defval != '':
-                                       print("")
-                                       print("The default value is: <code>%s</code>." % (
-                                               defval.replace('\\','\\\\')))
-                       print("")
-               # depends handling
-               if (node.hasAttribute('depends')):
-                       depends = node.getAttribute('depends')
-                       print("")
-                       print("%s \\ref cfg_%s \"%s\" is set to \\c YES." % (
-                               "This tag requires that the tag", depends.lower(), depends.upper()))
-               return False
+    # Handling part for documentation
+    name = node.getAttribute('id')
+    type = node.getAttribute('type')
+    format = node.getAttribute('format')
+    defval = node.getAttribute('defval')
+    adefval = node.getAttribute('altdefval')
+    depends = node.getAttribute('depends')
+    setting = node.getAttribute('setting')
+    doc = ""
+    if (type != 'obsolete'):
+        for n in node.childNodes:
+            if (n.nodeName == "docs"):
+                if (n.getAttribute('documentation') != "0"):
+                    if n.nodeType == Node.ELEMENT_NODE:
+                        doc += parseDocs(n)
+        if (first):
+            print(" \\anchor cfg_%s" % (name.lower()))
+            print("<dl>")
+            print("")
+            print("<dt>\\c %s <dd>" % (name))
+        else:
+            print(" \\anchor cfg_%s" % (name.lower()))
+            print("<dt>\\c %s <dd>" % (name))
+        print(" \\addindex %s" % (name))
+        print(doc)
+        if (type == 'enum'):
+            values = collectValues(node)
+            print("")
+            print("Possible values are: ")
+            rng = len(values)
+            for i in range(rng):
+                val = values[i]
+                if i == rng - 2:
+                    print("%s and " % (val))
+                elif i == rng - 1:
+                    print("%s." % (val))
+                else:
+                    print("%s, " % (val))
+            if (defval != ""):
+                print("")
+                print("")
+                print("The default value is: <code>%s</code>." % (defval))
+            print("")
+        elif (type == 'int'):
+            minval = node.getAttribute('minval')
+            maxval = node.getAttribute('maxval')
+            print("")
+            print("")
+            print("%s: %s%s%s, %s: %s%s%s, %s: %s%s%s." % (
+                     " Minimum value", "<code>", minval, "</code>", 
+                     "maximum value", "<code>", maxval, "</code>",
+                     "default value", "<code>", defval, "</code>"))
+            print("")
+        elif (type == 'bool'):
+            print("")
+            print("")
+            if (node.hasAttribute('altdefval')):
+                print("The default value is: system dependent.")
+            else:
+                print("The default value is: <code>%s</code>." % (
+                    "YES" if (defval == "1") else "NO"))
+            print("")
+        elif (type == 'list'):
+            if format == 'string':
+                values = collectValues(node)
+                rng = len(values)
+                for i in range(rng):
+                    val = values[i]
+                    if i == rng - 2:
+                        print("%s and " % (val))
+                    elif i == rng - 1:
+                        print("%s." % (val))
+                    else:
+                        print("%s, " % (val))
+            print("")
+        elif (type == 'string'):
+            if format == 'dir':
+                if defval != '':
+                    print("")
+                    print("The default directory is: <code>%s</code>." % (
+                        defval))
+            elif format == 'file':
+                abspath = node.getAttribute('abspath')
+                if defval != '':
+                    print("")
+                    if abspath != '1':
+                        print("The default file is: <code>%s</code>." % (
+                            defval))
+                    else:
+                        print("%s: %s%s%s." % (
+                            "The default file (with absolute path) is",
+                            "<code>",defval,"</code>"))
+                else:
+                    if abspath == '1':
+                        print("")
+                        print("The file has to be specified with full path.")
+            elif format =='image':
+                abspath = node.getAttribute('abspath')
+                if defval != '':
+                    print("")
+                    if abspath != '1':
+                        print("The default image is: <code>%s</code>." % (
+                            defval))
+                    else:
+                        print("%s: %s%s%s." % (
+                            "The default image (with absolute path) is",
+                            "<code>",defval,"</code>"))
+                else:
+                    if abspath == '1':
+                        print("")
+                        print("The image has to be specified with full path.")
+            else: # format == 'string':
+                if defval != '':
+                    print("")
+                    print("The default value is: <code>%s</code>." % (
+                        defval.replace('\\','\\\\')))
+            print("")
+        # depends handling
+        if (node.hasAttribute('depends')):
+            depends = node.getAttribute('depends')
+            print("")
+            print("%s \\ref cfg_%s \"%s\" is set to \\c YES." % (
+                "This tag requires that the tag", depends.lower(), depends.upper()))
+        return False
 
 
 def parseGroupsDoc(node):
-       name = node.getAttribute('name')
-       doc = node.getAttribute('docs')
-       print("\section config_%s %s" % (name.lower(), doc))
-       # Start of list has been moved to the first option for better
-       # anchor placement
-       #  print "<dl>"
-       #  print ""
-       first = True
-       for n in node.childNodes:
-               if n.nodeType == Node.ELEMENT_NODE:
-                       first = parseOptionDoc(n, first)
-       if (not first):
-               print("</dl>")
+    name = node.getAttribute('name')
+    doc = node.getAttribute('docs')
+    print("\section config_%s %s" % (name.lower(), doc))
+    # Start of list has been moved to the first option for better
+    # anchor placement
+    #  print "<dl>"
+    #  print ""
+    first = True
+    for n in node.childNodes:
+        if n.nodeType == Node.ELEMENT_NODE:
+            first = parseOptionDoc(n, first)
+    if (not first):
+        print("</dl>")
 
 
 def parseGroupsList(node, commandsList):
-       list = ()
-       for n in node.childNodes:
-               if n.nodeType == Node.ELEMENT_NODE:
-                       type = n.getAttribute('type')
-                       if type != 'obsolete':
-                               commandsList = commandsList + (n.getAttribute('id'),)
-       return commandsList
+    list = ()
+    for n in node.childNodes:
+        if n.nodeType == Node.ELEMENT_NODE:
+            type = n.getAttribute('type')
+            if type != 'obsolete':
+                commandsList = commandsList + (n.getAttribute('id'),)
+    return commandsList
 
 
 def parseDocs(node):
-       doc = ""
-       for n in node.childNodes:
-               if n.nodeType == Node.TEXT_NODE:
-                       doc += n.nodeValue.strip()
-               if n.nodeType == Node.CDATA_SECTION_NODE:
-                       doc += n.nodeValue.rstrip("\r\n ").lstrip("\r\n")
-       #doc += "<br>"
-       return doc
+    doc = ""
+    for n in node.childNodes:
+        if n.nodeType == Node.TEXT_NODE:
+            doc += n.nodeValue.strip()
+        if n.nodeType == Node.CDATA_SECTION_NODE:
+            doc += n.nodeValue.rstrip("\r\n ").lstrip("\r\n")
+    #doc += "<br>"
+    return doc
 
 
 def parseHeaderDoc(node):
-       doc = ""
-       for n in node.childNodes:
-               if n.nodeType == Node.ELEMENT_NODE:
-                       if (n.nodeName == "docs"):
-                               if (n.getAttribute('documentation') != "0"):
-                                       doc += parseDocs(n)
-       print(doc)
+    doc = ""
+    for n in node.childNodes:
+        if n.nodeType == Node.ELEMENT_NODE:
+            if (n.nodeName == "docs"):
+                if (n.getAttribute('documentation') != "0"):
+                    doc += parseDocs(n)
+    print(doc)
 
 
 def parseFooterDoc(node):
-       doc = ""
-       for n in node.childNodes:
-               if n.nodeType == Node.ELEMENT_NODE:
-                       if (n.nodeName == "docs"):
-                               if (n.getAttribute('documentation') != "0"):
-                                       doc += parseDocs(n)
-       print(doc)
+    doc = ""
+    for n in node.childNodes:
+        if n.nodeType == Node.ELEMENT_NODE:
+            if (n.nodeName == "docs"):
+                if (n.getAttribute('documentation') != "0"):
+                    doc += parseDocs(n)
+    print(doc)
 
 
 def main():
-       if len(sys.argv)<3 or (not sys.argv[1] in ['-doc','-cpp','-wiz','-maph','-maps']):
-               sys.exit('Usage: %s -doc|-cpp|-wiz|-maph|-maps config.xml' % sys.argv[0])
-       try:
-               doc = xml.dom.minidom.parse(sys.argv[2])
-       except Exception as inst:
-               sys.stdout = sys.stderr
-               print("")
-               print(inst)
-               print("")
-               sys.exit(1)
-       elem = doc.documentElement
-       if (sys.argv[1] == "-doc"):
-               print("/* WARNING: This file is generated!")
-               print(" * Do not edit this file, but edit config.xml instead and run")
-               print(" * python configgen.py -doc config.xml to regenerate this file!")
-               print(" */")
-               # process header
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if (n.nodeName == "header"):
-                                       parseHeaderDoc(n)
-               # generate list with all commands
-               commandsList = ()
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if (n.nodeName == "group"):
-                                       commandsList = parseGroupsList(n, commandsList)
-               print("\\secreflist")
-               for x in sorted(commandsList):
-                       print("\\refitem cfg_%s %s" % (x.lower(), x))
-               print("\\endsecreflist")
-               # process groups and options
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if (n.nodeName == "group"):
-                                       parseGroupsDoc(n)
-               # process footers
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if (n.nodeName == "footer"):
-                                       parseFooterDoc(n)
-       elif (sys.argv[1] == "-maph"):
-               print("/* WARNING: This file is generated!")
-               print(" * Do not edit this file, but edit config.xml instead and run")
-               print(" * python configgen.py -map config.xml to regenerate this file!")
-               print(" */")
-               print("#ifndef CONFIGVALUES_H")
-               print("#define CONFIGVALUES_H")
-               print("")
-               print("#include \"qcstring.h\"")
-               print("#include \"containers.h\"")
-               print("#include \"settings.h\"")
-               print("")
-               print("class ConfigValues")
-               print("{")
-               print("  public:")
-               print("    static ConfigValues &instance() { static ConfigValues theInstance; return theInstance; }")
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if n.nodeName == "group":
-                                       parseGroupMapGetter(n)
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if n.nodeName == "group":
-                                       parseGroupMapSetter(n)
-               print("    void init();")
-               print("    StringVector fields() const;")
-               print("    struct Info")
-               print("    {")
-               print("      enum Type { Bool, Int, String, List, Unknown };")
-               print("      Info(Type t,bool         ConfigValues::*b) : type(t), value(b) {}")
-               print("      Info(Type t,int          ConfigValues::*i) : type(t), value(i) {}")
-               print("      Info(Type t,QCString     ConfigValues::*s) : type(t), value(s) {}")
-               print("      Info(Type t,StringVector ConfigValues::*l) : type(t), value(l) {}")
-               print("      Type type;")
-               print("      union Item")
-               print("      {")
-               print("        Item(bool         ConfigValues::*v) : b(v) {}")
-               print("        Item(int          ConfigValues::*v) : i(v) {}")
-               print("        Item(QCString     ConfigValues::*v) : s(v) {}")
-               print("        Item(StringVector ConfigValues::*v) : l(v) {}")
-               print("        bool         ConfigValues::*b;")
-               print("        int          ConfigValues::*i;")
-               print("        QCString     ConfigValues::*s;")
-               print("        StringVector ConfigValues::*l;")
-               print("      } value;")
-               print("    };")
-               print("    const Info *get(const QCString &tag) const;")
-               print("  private:")
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if (n.nodeName == "group"):
-                                       parseGroupMapVar(n)
-               print("};")
-               print("")
-               print("#endif")
-       elif (sys.argv[1] == "-maps"):
-               print("/* WARNING: This file is generated!")
-               print(" * Do not edit this file, but edit config.xml instead and run")
-               print(" * python configgen.py -maps config.xml to regenerate this file!")
-               print(" */")
-               print("#include \"configvalues.h\"")
-               print("#include \"configimpl.h\"")
-               print("#include <unordered_map>")
-               print("")
-               print("const ConfigValues::Info *ConfigValues::get(const QCString &tag) const");
-               print("{");
-               print("  static const std::unordered_map< std::string, Info > configMap =");
-               print("  {");
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if (n.nodeName == "group"):
-                                       parseGroupMapInit(n)
-               print("  };");
-               print("  auto it = configMap.find(tag.str());");
-               print("  return it!=configMap.end() ? &it->second : nullptr;");
-               print("}");
-               print("")
-               print("void ConfigValues::init()")
-               print("{")
-               print("  static bool first = TRUE;")
-               print("  if (!first) return;")
-               print("  first = FALSE;")
-               print("")
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if (n.nodeName == "group"):
-                                       parseGroupInit(n)
-               print("}")
-               print("")
-               print("StringVector ConfigValues::fields() const")
-               print("{")
-               print("  return {");
-               first=True
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if (n.nodeName == "group"):
-                                       for c in n.childNodes:
-                                               if c.nodeType == Node.ELEMENT_NODE:
-                                                       name = c.getAttribute('id')
-                                                       type = c.getAttribute('type')
-                                                       if type!='obsolete':
-                                                               if not first:
-                                                                       print(",")
-                                                               first=False
-                                                               sys.stdout.write('    "'+name+'"')
-               print("")
-               print("  };")
-               print("}")
-       elif (sys.argv[1] == "-cpp"):
-               print("/* WARNING: This file is generated!")
-               print(" * Do not edit this file, but edit config.xml instead and run")
-               print(" * python configgen.py -cpp config.xml to regenerate this file!")
-               print(" */")
-               print("")
-               print("#include \"configoptions.h\"")
-               print("#include \"configimpl.h\"")
-               print("#include \"portable.h\"")
-               print("#include \"settings.h\"")
-               print("")
-               print("void addConfigOptions(ConfigImpl *cfg)")
-               print("{")
-               print("  ConfigString *cs;")
-               print("  ConfigEnum   *ce;")
-               print("  ConfigList   *cl;")
-               print("  ConfigInt    *ci;")
-               print("  ConfigBool   *cb;")
-               print("")
-               # process header
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if (n.nodeName == "header"):
-                                       parseHeader(n,'cfg')
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if (n.nodeName == "group"):
-                                       parseGroups(n)
-               print("}")
-       elif (sys.argv[1] == "-wiz"):
-               print("/* WARNING: This file is generated!")
-               print(" * Do not edit this file, but edit config.xml instead and run")
-               print(" * python configgen.py -wiz config.xml to regenerate this file!")
-               print(" */")
-               print("#include \"configdoc.h\"")
-               print("#include \"docintf.h\"")
-               print("")
-               print("void addConfigDocs(DocIntf *doc)")
-               print("{")
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if (n.nodeName == "header"):
-                                       parseHeader(n,'doc')
-               for n in elem.childNodes:
-                       if n.nodeType == Node.ELEMENT_NODE:
-                               if (n.nodeName == "group"):
-                                       parseGroupCDocs(n)
-               print("}")
+    if len(sys.argv)<3 or (not sys.argv[1] in ['-doc','-cpp','-wiz','-maph','-maps']):
+        sys.exit('Usage: %s -doc|-cpp|-wiz|-maph|-maps config.xml' % sys.argv[0])
+    try:
+        doc = xml.dom.minidom.parse(sys.argv[2])
+    except Exception as inst:
+        sys.stdout = sys.stderr
+        print("")
+        print(inst)
+        print("")
+        sys.exit(1)
+    elem = doc.documentElement
+    if (sys.argv[1] == "-doc"):
+        print("/* WARNING: This file is generated!")
+        print(" * Do not edit this file, but edit config.xml instead and run")
+        print(" * python configgen.py -doc config.xml to regenerate this file!")
+        print(" */")
+        # process header
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if (n.nodeName == "header"):
+                    parseHeaderDoc(n)
+        # generate list with all commands
+        commandsList = ()
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if (n.nodeName == "group"):
+                    commandsList = parseGroupsList(n, commandsList)
+        print("\\secreflist")
+        for x in sorted(commandsList):
+            print("\\refitem cfg_%s %s" % (x.lower(), x))
+        print("\\endsecreflist")
+        # process groups and options
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if (n.nodeName == "group"):
+                    parseGroupsDoc(n)
+        # process footers
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if (n.nodeName == "footer"):
+                    parseFooterDoc(n)
+    elif (sys.argv[1] == "-maph"):
+        print("/* WARNING: This file is generated!")
+        print(" * Do not edit this file, but edit config.xml instead and run")
+        print(" * python configgen.py -map config.xml to regenerate this file!")
+        print(" */")
+        print("#ifndef CONFIGVALUES_H")
+        print("#define CONFIGVALUES_H")
+        print("")
+        print("#include <string>")
+        print("#include <unordered_map>")
+        print("#include \"qcstring.h\"")
+        print("#include \"containers.h\"")
+        print("#include \"settings.h\"")
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if n.nodeName == "group":
+                    parseGroupMapEnums(n)
+        print("")
+        print("class ConfigValues")
+        print("{")
+        print("  public:")
+        print("    static ConfigValues &instance() { static ConfigValues theInstance; return theInstance; }")
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if n.nodeName == "group":
+                    parseGroupMapGetter(n)
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if n.nodeName == "group":
+                    parseGroupMapSetter(n)
+        print("    void init();")
+        print("    StringVector fields() const;")
+        print("    struct Info")
+        print("    {")
+        print("      enum Type { Bool, Int, String, List, Unknown };")
+        print("      Info(Type t,bool         ConfigValues::*b) : type(t), value(b) {}")
+        print("      Info(Type t,int          ConfigValues::*i) : type(t), value(i) {}")
+        print("      Info(Type t,QCString     ConfigValues::*s) : type(t), value(s) {}")
+        print("      Info(Type t,StringVector ConfigValues::*l) : type(t), value(l) {}")
+        print("      Type type;")
+        print("      union Item")
+        print("      {")
+        print("        Item(bool         ConfigValues::*v) : b(v) {}")
+        print("        Item(int          ConfigValues::*v) : i(v) {}")
+        print("        Item(QCString     ConfigValues::*v) : s(v) {}")
+        print("        Item(StringVector ConfigValues::*v) : l(v) {}")
+        print("        bool         ConfigValues::*b;")
+        print("        int          ConfigValues::*i;")
+        print("        QCString     ConfigValues::*s;")
+        print("        StringVector ConfigValues::*l;")
+        print("      } value;")
+        print("    };")
+        print("    const Info *get(const QCString &tag) const;")
+        print("  private:")
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if (n.nodeName == "group"):
+                    parseGroupMapVar(n)
+        print("};")
+        print("")
+        print("#endif")
+    elif (sys.argv[1] == "-maps"):
+        print("/* WARNING: This file is generated!")
+        print(" * Do not edit this file, but edit config.xml instead and run")
+        print(" * python configgen.py -maps config.xml to regenerate this file!")
+        print(" */")
+        print("#include \"configvalues.h\"")
+        print("#include \"configimpl.h\"")
+        print("#include <unordered_map>")
+        print("")
+        print("const ConfigValues::Info *ConfigValues::get(const QCString &tag) const");
+        print("{");
+        print("  static const std::unordered_map< std::string, Info > configMap =");
+        print("  {");
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if (n.nodeName == "group"):
+                    parseGroupMapInit(n)
+        print("  };");
+        print("  auto it = configMap.find(tag.str());");
+        print("  return it!=configMap.end() ? &it->second : nullptr;");
+        print("}");
+        print("")
+        print("void ConfigValues::init()")
+        print("{")
+        print("  static bool first = TRUE;")
+        print("  if (!first) return;")
+        print("  first = FALSE;")
+        print("")
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if (n.nodeName == "group"):
+                    parseGroupInit(n)
+        print("}")
+        print("")
+        print("StringVector ConfigValues::fields() const")
+        print("{")
+        print("  return {");
+        first=True
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if (n.nodeName == "group"):
+                    for c in n.childNodes:
+                        if c.nodeType == Node.ELEMENT_NODE:
+                            name = c.getAttribute('id')
+                            type = c.getAttribute('type')
+                            if type!='obsolete':
+                                if not first:
+                                    print(",")
+                                first=False
+                                sys.stdout.write('    "'+name+'"')
+        print("")
+        print("  };")
+        print("}")
+    elif (sys.argv[1] == "-cpp"):
+        print("/* WARNING: This file is generated!")
+        print(" * Do not edit this file, but edit config.xml instead and run")
+        print(" * python configgen.py -cpp config.xml to regenerate this file!")
+        print(" */")
+        print("")
+        print("#include \"configoptions.h\"")
+        print("#include \"configimpl.h\"")
+        print("#include \"portable.h\"")
+        print("#include \"settings.h\"")
+        print("")
+        print("void addConfigOptions(ConfigImpl *cfg)")
+        print("{")
+        print("  ConfigString *cs;")
+        print("  ConfigEnum   *ce;")
+        print("  ConfigList   *cl;")
+        print("  ConfigInt    *ci;")
+        print("  ConfigBool   *cb;")
+        print("")
+        # process header
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if (n.nodeName == "header"):
+                    parseHeader(n,'cfg')
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if (n.nodeName == "group"):
+                    parseGroups(n)
+        print("}")
+    elif (sys.argv[1] == "-wiz"):
+        print("/* WARNING: This file is generated!")
+        print(" * Do not edit this file, but edit config.xml instead and run")
+        print(" * python configgen.py -wiz config.xml to regenerate this file!")
+        print(" */")
+        print("#include \"configdoc.h\"")
+        print("#include \"docintf.h\"")
+        print("")
+        print("void addConfigDocs(DocIntf *doc)")
+        print("{")
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if (n.nodeName == "header"):
+                    parseHeader(n,'doc')
+        for n in elem.childNodes:
+            if n.nodeType == Node.ELEMENT_NODE:
+                if (n.nodeName == "group"):
+                    parseGroupCDocs(n)
+        print("}")
 
 if __name__ == '__main__':
-       main()
+    main()
index e828491..4906391 100644 (file)
@@ -134,6 +134,7 @@ class ConfigList : public ConfigOption
     WidgetType widgetType() const { return m_widgetType; }
     StringVector *valueRef() { return &m_value; }
     StringVector getDefault() { return m_defaultValue; }
+    void emptyValueToDefault() { if (m_value.empty() && !m_defaultValue.empty()) m_value=m_defaultValue; };
     void writeTemplate(TextStream &t,bool sl,bool);
     void compareDoxyfile(TextStream &t);
     void writeXMLDoxyfile(TextStream &t);
@@ -181,7 +182,7 @@ class ConfigEnum : public ConfigOption
 class ConfigString : public ConfigOption
 {
   public:
-    enum WidgetType { String, File, Dir, Image };
+    enum WidgetType { String, File, Dir, Image, FileAndDir };
     ConfigString(const char *name,const char *doc)
       : ConfigOption(O_String)
     {
@@ -278,12 +279,22 @@ class ConfigBool : public ConfigOption
 class ConfigObsolete : public ConfigOption
 {
   public:
-    ConfigObsolete(const char *name) : ConfigOption(O_Obsolete)
+    ConfigObsolete(const char *name,OptionType orgType) : ConfigOption(O_Obsolete), m_orgType(orgType)
     { m_name = name; }
     void writeTemplate(TextStream &,bool,bool);
     void compareDoxyfile(TextStream &) {}
     void writeXMLDoxyfile(TextStream &) {}
     void substEnvVars() {}
+    OptionType orgType() const { return m_orgType; }
+    StringVector *valueListRef() { return &m_listvalue; }
+    QCString *valueStringRef() { return &m_valueString; }
+    void markAsPresent() { m_present = true; }
+    bool isPresent() const { return m_present; }
+  private:
+    OptionType m_orgType;
+    StringVector m_listvalue;
+    QCString m_valueString;
+    bool m_present = false;
 };
 
 /** Section marker for compile time optional options
@@ -468,9 +479,9 @@ class ConfigImpl
       return result;
     }
     /*! Adds an option that has become obsolete. */
-    ConfigOption *addObsolete(const char *name)
+    ConfigOption *addObsolete(const char *name,ConfigOption::OptionType orgType)
     {
-      ConfigObsolete *result = new ConfigObsolete(name);
+      ConfigObsolete *result = new ConfigObsolete(name,orgType);
       m_obsolete.push_back(std::unique_ptr<ConfigOption>(result));
       m_dict.insert(std::make_pair(name,result));
       return result;
index a72057e..f3ce092 100644 (file)
@@ -210,23 +210,40 @@ void ConfigInt::convertStrToVal()
   }
 }
 
-void ConfigBool::convertStrToVal()
+static bool convertStringToBool(const QCString &str,bool &isValid)
 {
-  QCString val = m_valueString.stripWhiteSpace().lower();
+  isValid=false;
+  QCString val = str.stripWhiteSpace().lower();
   if (!val.isEmpty())
   {
     if (val=="yes" || val=="true" || val=="1" || val=="all")
     {
-      m_value=TRUE;
+      isValid=true;
+      return true;
     }
     else if (val=="no" || val=="false" || val=="0" || val=="none")
     {
-      m_value=FALSE;
+      isValid=true;
+      return false;
+    }
+  }
+  return false;
+}
+
+void ConfigBool::convertStrToVal()
+{
+  if (!m_valueString.stripWhiteSpace().isEmpty())
+  {
+    bool isValid=false;
+    bool b = convertStringToBool(m_valueString,isValid);
+    if (isValid)
+    {
+      m_value=b;
     }
     else
     {
       config_warn("argument '%s' for option %s is not a valid boolean value\n"
-                "Using the default: %s!\n",qPrint(m_valueString),qPrint(m_name),m_value?"YES":"NO");
+          "Using the default: %s!\n",qPrint(m_valueString),qPrint(m_name),m_value?"YES":"NO");
     }
   }
 }
@@ -598,6 +615,11 @@ static ConfigImpl       *g_config;
 #undef  YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#define LEX_NO_REENTRANT
+#include "doxygen_lex.h"
+
 static yy_size_t yyread(char *buf,yy_size_t max_size)
 {
   // no file included
@@ -1004,7 +1026,20 @@ static void readIncludeFile(const QCString &incName)
                                                               "         To avoid this warning please remove this line from your configuration "
                                                               "file or upgrade it using \"doxygen -u\"\n", qPrint(g_cmd),g_yyLineNr,qPrint(g_yyFileName));
                                                  }
-                                                 BEGIN(SkipInvalid);
+                                                 ((ConfigObsolete*)option)->markAsPresent();
+                                                 if (((ConfigObsolete*)option)->orgType()==ConfigOption::O_List)
+                                                 {
+                                                   g_list = ((ConfigObsolete*)option)->valueListRef();
+                                                   g_list->clear();
+                                                   g_listStr="";
+                                                   BEGIN(GetStrList);
+                                                 }
+                                                 else
+                                                 {
+                                                   g_string = ((ConfigObsolete*)option)->valueStringRef();
+                                                   g_string->resize(0);
+                                                   BEGIN(GetString);
+                                                 }
                                                  break;
                                                case ConfigOption::O_Disabled:
                                                  if (g_configUpdate)
@@ -1058,7 +1093,16 @@ static void readIncludeFile(const QCString &incName)
                                                  config_warn("Tag '%s' at line %d of file %s has become obsolete.\n"
                                                             "To avoid this warning please update your configuration "
                                                             "file using \"doxygen -u\"\n", qPrint(g_cmd),g_yyLineNr,qPrint(g_yyFileName));
-                                                 BEGIN(SkipInvalid);
+                                                 if (((ConfigObsolete*)option)->orgType()==ConfigOption::O_List)
+                                                 {
+                                                   g_list = ((ConfigObsolete*)option)->valueListRef();
+                                                   g_listStr="";
+                                                   BEGIN(GetStrList);
+                                                 }
+                                                 else
+                                                 {
+                                                   BEGIN(SkipInvalid);
+                                                 }
                                                  break;
                                                case ConfigOption::O_Disabled:
                                                  config_warn("Tag '%s' at line %d of file %s belongs to an option that was not enabled at compile time.\n"
@@ -1512,7 +1556,36 @@ static void checkList(const StringVector &list,const char *name, bool equalRequi
   }
 }
 
-void Config::checkAndCorrect(bool quiet)
+static void adjustBoolSetting(const char *depOption, const char *optionName,bool expectedValue)
+{
+  // lookup option by name
+  const ConfigValues::Info *option = ConfigValues::instance().get(optionName);
+  if (option && option->type==ConfigValues::Info::Bool) // safety check
+  {
+    if (ConfigValues::instance().*(option->value.b)!=expectedValue) // current value differs from expectation
+    {
+      err("When enabling %s the %s option should be disabled. I'll adjust it for you.\n",depOption,optionName);
+      ConfigValues::instance().*(option->value.b)=expectedValue; // adjust option
+    }
+  }
+}
+
+static void adjustStringSetting(const char *depOption, const char *optionName,const QCString &expectedValue)
+{
+  // lookup option by name
+  const ConfigValues::Info *option = ConfigValues::instance().get(optionName);
+  if (option && option->type==ConfigValues::Info::String) // safety check
+  {
+    if (ConfigValues::instance().*(option->value.s)!=expectedValue) // current value differs from expectation
+    {
+      err("When enabling %s the %s option should have value '%s'. I'll adjust it for you.\n",depOption,optionName,qPrint(expectedValue));
+      ConfigValues::instance().*(option->value.s)=expectedValue; // adjust option
+    }
+  }
+}
+
+
+void Config::checkAndCorrect(bool quiet, const bool check)
 {
   ConfigValues::instance().init();
 
@@ -1520,69 +1593,34 @@ void Config::checkAndCorrect(bool quiet)
   //------------------------
   // check WARN_FORMAT
   QCString warnFormat = Config_getString(WARN_FORMAT);
-  if (warnFormat.stripWhiteSpace().isEmpty())
+  if (warnFormat.find("$file")==-1)
   {
-    Config_updateString(WARN_FORMAT,"$file:$line $text");
+    warn_uncond("warning format does not contain a $file tag!\n");
   }
-  else
+  if (warnFormat.find("$line")==-1)
   {
-    if (warnFormat.find("$file")==-1)
-    {
-      warn_uncond("warning format does not contain a $file tag!\n");
-    }
-    if (warnFormat.find("$line")==-1)
-    {
-      warn_uncond("warning format does not contain a $line tag!\n");
-    }
-    if (warnFormat.find("$text")==-1)
-    {
-      warn_uncond("warning format foes not contain a $text tag!\n");
-    }
+    warn_uncond("warning format does not contain a $line tag!\n");
   }
-
-  //------------------------
-  // set default man page extension if non is given by the user
-  QCString manExtension = Config_getString(MAN_EXTENSION);
-  if (manExtension.isEmpty())
+  if (warnFormat.find("$text")==-1)
   {
-    Config_updateString(MAN_EXTENSION,".3");
+    warn_uncond("warning format foes not contain a $text tag!\n");
   }
 
   //------------------------
   // check and correct PAPER_TYPE
-  QCString paperType = Config_getEnum(PAPER_TYPE);
+  QCString paperType = Config_getEnumAsString(PAPER_TYPE);
   paperType=paperType.lower().stripWhiteSpace();
   if (paperType.isEmpty() || paperType=="a4wide")
   {
-    paperType = "a4";
-  }
-  if (paperType!="a4" && paperType!="letter" &&
-      paperType!="legal" && paperType!="executive")
-  {
-    err("Unknown page type specified\n");
-    paperType="a4";
-  }
-  Config_updateEnum(PAPER_TYPE,paperType);
-
-  //------------------------
-  // check & correct OUTPUT_LANGUAGE
-  QCString outputLanguage=Config_getEnum(OUTPUT_LANGUAGE);
-  outputLanguage=outputLanguage.stripWhiteSpace();
-  if (outputLanguage.isEmpty())
-  {
-    outputLanguage = "English";
+    // use a4
+    Config_updateEnum(PAPER_TYPE,PAPER_TYPE_t::a4);
   }
-  Config_updateEnum(OUTPUT_LANGUAGE,outputLanguage);
-
-  //------------------------
-  // check & correct HTML_FILE_EXTENSION
-  QCString htmlFileExtension=Config_getString(HTML_FILE_EXTENSION);
-  htmlFileExtension=htmlFileExtension.stripWhiteSpace();
-  if (htmlFileExtension.isEmpty())
+  else if (paperType!="a4" && paperType!="letter" &&
+           paperType!="legal" && paperType!="executive")
   {
-    htmlFileExtension = ".html";
+    err("Unknown page type '%s' specified\n",qPrint(paperType));
+    Config_updateEnum(PAPER_TYPE,PAPER_TYPE_t::a4);
   }
-  Config_updateString(HTML_FILE_EXTENSION,htmlFileExtension);
 
   //------------------------
   // check & correct STRIP_FROM_PATH
@@ -1607,7 +1645,7 @@ void Config::checkAndCorrect(bool quiet)
   //------------------------
   // Test to see if HTML header is valid
   QCString headerFile = Config_getString(HTML_HEADER);
-  if (!headerFile.isEmpty())
+  if (check && !headerFile.isEmpty())
   {
     FileInfo fi(headerFile.str());
     if (!fi.exists())
@@ -1620,7 +1658,7 @@ void Config::checkAndCorrect(bool quiet)
   //------------------------
   // Test to see if HTML footer is valid
   QCString footerFile = Config_getString(HTML_FOOTER);
-  if (!footerFile.isEmpty())
+  if (check && !footerFile.isEmpty())
   {
     FileInfo fi(footerFile.str());
     if (!fi.exists())
@@ -1634,25 +1672,25 @@ void Config::checkAndCorrect(bool quiet)
   // Test to see if MathJax code file is valid
   if (Config_getBool(USE_MATHJAX))
   {
-    QCString mathJaxFormat = Config_getEnum(MATHJAX_FORMAT);
-    QCString mathjaxVersion = Config_getEnum(MATHJAX_VERSION);
-    if (!mathJaxFormat.isEmpty())
+    auto mathJaxFormat = Config_getEnum(MATHJAX_FORMAT);
+    auto mathjaxVersion = Config_getEnum(MATHJAX_VERSION);
+    if (mathjaxVersion == MATHJAX_VERSION_t::MathJax_2)
     {
-      if (mathjaxVersion == "MathJax_2")
+      if (mathJaxFormat==MATHJAX_FORMAT_t::chtml)
       {
-        if (mathJaxFormat=="chtml") Config_updateEnum(MATHJAX_FORMAT,"HTML-CSS");
+        Config_updateEnum(MATHJAX_FORMAT,MATHJAX_FORMAT_t::HTML_CSS);
       }
-      else
+    }
+    else
+    {
+      if (mathJaxFormat==MATHJAX_FORMAT_t::HTML_CSS || mathJaxFormat==MATHJAX_FORMAT_t::NativeMML)
       {
-        if (mathJaxFormat=="HTML-CSS" || mathJaxFormat=="NativeMML")
-        {
-          Config_updateEnum(MATHJAX_FORMAT,"chtml");
-        }
+        Config_updateEnum(MATHJAX_FORMAT,MATHJAX_FORMAT_t::chtml);
       }
     }
 
     QCString mathJaxCodefile = Config_getString(MATHJAX_CODEFILE);
-    if (!mathJaxCodefile.isEmpty())
+    if (check && !mathJaxCodefile.isEmpty())
     {
       FileInfo fi(mathJaxCodefile.str());
       if (!fi.exists())
@@ -1664,13 +1702,11 @@ void Config::checkAndCorrect(bool quiet)
     QCString path = Config_getString(MATHJAX_RELPATH);
     if (path.isEmpty())
     {
-      if (mathjaxVersion == "MathJax_2")
-      {
-        path = "https://cdn.jsdelivr.net/npm/mathjax@2";
-      }
-      else
+      path = "https://cdn.jsdelivr.net/npm/mathjax@";
+      switch (mathjaxVersion)
       {
-        path = "https://cdn.jsdelivr.net/npm/mathjax@3";
+        case MATHJAX_VERSION_t::MathJax_2: path += "2"; break;
+        case MATHJAX_VERSION_t::MathJax_3: path += "3"; break;
       }
     }
 
@@ -1684,7 +1720,7 @@ void Config::checkAndCorrect(bool quiet)
   //------------------------
   // Test to see if LaTeX header is valid
   QCString latexHeaderFile = Config_getString(LATEX_HEADER);
-  if (!latexHeaderFile.isEmpty())
+  if (check && !latexHeaderFile.isEmpty())
   {
     FileInfo fi(latexHeaderFile.str());
     if (!fi.exists())
@@ -1697,7 +1733,7 @@ void Config::checkAndCorrect(bool quiet)
   //------------------------
   // Test to see if LaTeX footer is valid
   QCString latexFooterFile = Config_getString(LATEX_FOOTER);
-  if (!latexFooterFile.isEmpty())
+  if (check && !latexFooterFile.isEmpty())
   {
     FileInfo fi(latexFooterFile.str());
     if (!fi.exists())
@@ -1774,74 +1810,32 @@ void Config::checkAndCorrect(bool quiet)
   }
 
   //------------------------
-  // check if GENERATE_TREEVIEW and GENERATE_HTMLHELP are both enabled
-  if (Config_getBool(GENERATE_TREEVIEW) && Config_getBool(GENERATE_HTMLHELP))
-  {
-    err("When enabling GENERATE_HTMLHELP the tree view (GENERATE_TREEVIEW) should be disabled. I'll do it for you.\n");
-    Config_updateBool(GENERATE_TREEVIEW,FALSE);
-  }
-
-  //------------------------
-  // check if GENERATE_HTMLHELP and HTML_FILE_EXTENSION is not .html
-  if (Config_getString(HTML_FILE_EXTENSION)!=".html" && Config_getBool(GENERATE_HTMLHELP))
-  {
-    err("When enabling GENERATE_HTMLHELP the HTML_FILE_EXTENSION should be \".html\". I'll do it for you.\n");
-    Config_updateString(HTML_FILE_EXTENSION,".html");
-  }
 
-  //------------------------
-  // check if SEARCHENGINE and GENERATE_HTMLHELP are both enabled
-  if (Config_getBool(SEARCHENGINE) && Config_getBool(GENERATE_HTMLHELP))
+  // check for settings that are inconsistent with having GENERATE_HTMLHELP enabled
+  if (Config_getBool(GENERATE_HTMLHELP))
   {
-    err("When enabling GENERATE_HTMLHELP the search engine (SEARCHENGINE) should be disabled. I'll do it for you.\n");
-    Config_updateBool(SEARCHENGINE,FALSE);
+    const char *depOption = "GENERATE_HTMLHELP";
+    adjustBoolSetting(  depOption, "GENERATE_TREEVIEW",   false  );
+    adjustBoolSetting(  depOption, "SEARCHENGINE",        false  );
+    adjustStringSetting(depOption, "HTML_FILE_EXTENSION", ".html");
   }
 
-  //------------------------
-  // check if SEPARATE_MEMBER_PAGES and INLINE_GROUPED_CLASSES are both enabled
-  if (Config_getBool(SEPARATE_MEMBER_PAGES) && Config_getBool(INLINE_GROUPED_CLASSES))
+  // check for settings that are inconsistent with having INLINE_GROUPED_CLASSES enabled
+  if (Config_getBool(INLINE_GROUPED_CLASSES))
   {
-    err("When enabling INLINE_GROUPED_CLASSES the SEPARATE_MEMBER_PAGES option should be disabled. I'll do it for you.\n");
-    Config_updateBool(SEPARATE_MEMBER_PAGES,FALSE);
+    const char *depOption = "INLINE_GROUPED_CLASSES";
+    adjustBoolSetting(depOption, "SEPARATE_MEMBER_PAGES", false);
   }
 
   //------------------------
-  // check and correct DOT_IMAGE_FORMAT
-  QCString dotImageFormat=Config_getEnum(DOT_IMAGE_FORMAT);
-  dotImageFormat=dotImageFormat.stripWhiteSpace();
-  if (dotImageFormat.isEmpty())
-  {
-    dotImageFormat = "png";
-  }
-  Config_updateEnum(DOT_IMAGE_FORMAT,dotImageFormat);
-
-  //------------------------
   // correct DOT_FONTNAME if needed
   QCString dotFontName=Config_getString(DOT_FONTNAME);
   if (dotFontName=="FreeSans" || dotFontName=="FreeSans.ttf")
   {
     warn_uncond("doxygen no longer ships with the FreeSans font.\n"
-               "You may want to clear or change DOT_FONTNAME.\n"
-               "Otherwise you run the risk that the wrong font is being used for dot generated graphs.\n");
-  }
-  else if (dotFontName.isEmpty())
-  {
-    dotFontName = "Helvetica";
+               "  You may want to clear or change DOT_FONTNAME.\n"
+               "  Otherwise you run the risk that the wrong font is being used for dot generated graphs.\n");
   }
-  Config_updateString(DOT_FONTNAME,dotFontName);
-
-  //------------------------
-  // clip dotFontSize against the maximum bounds
-  int dotFontSize = Config_getInt(DOT_FONTSIZE);
-  if (dotFontSize<4)
-  {
-    dotFontSize=4;
-  }
-  else if (dotFontSize>24)
-  {
-    dotFontSize=24;
-  }
-  Config_updateInt(DOT_FONTSIZE,dotFontSize);
 
   //------------------------
   // clip number of threads
@@ -1884,12 +1878,8 @@ void Config::checkAndCorrect(bool quiet)
     uint i=0,l=dotPath.length();
     for (i=0;i<l;i++) if (dotPath.at(i)=='/') dotPath.at(i)='\\';
 #endif
+    Config_updateString(DOT_PATH,dotPath);
   }
-  else // make sure the string is empty but not null!
-  {
-    dotPath="";
-  }
-  Config_updateString(DOT_PATH,dotPath);
 
   //------------------------
   // check plantuml path
@@ -1903,27 +1893,27 @@ void Config::checkAndCorrect(bool quiet)
       FileInfo jar(plantumlJar.str());
       if (jar.exists() && jar.isFile())
       {
-        plantumlJarPath = jar.dirPath(TRUE)+Portable::pathSeparator();
+        plantumlJarPath = plantumlJar;
       }
       else
       {
-        err("Jar file plantuml.jar not found at location "
+        err("Jar file 'plantuml.jar' not found at location "
                    "specified via PLANTUML_JAR_PATH: '%s'\n",qPrint(plantumlJarPath));
         plantumlJarPath="";
       }
     }
-    else if (pu.exists() && pu.isFile() && plantumlJarPath.right(4)==".jar") // PLANTUML_JAR_PATH is file
+    else if (pu.exists() && pu.isFile()) // PLANTUML_JAR_PATH is file
     {
-      plantumlJarPath = pu.dirPath(TRUE)+Portable::pathSeparator();
+      // Nothing to be done
     }
     else
     {
-      err("path specified via PLANTUML_JAR_PATH does not exist or not a directory: %s\n",
+      err("PLANTUML_JAR_PATH is not a directory with a 'plantuml.jar' file or is not an existing file: %s\n",
                  qPrint(plantumlJarPath));
       plantumlJarPath="";
     }
+    Config_updateString(PLANTUML_JAR_PATH,plantumlJarPath);
   }
-  Config_updateString(PLANTUML_JAR_PATH,plantumlJarPath);
 
   //------------------------
   // check dia path
@@ -1945,12 +1935,8 @@ void Config::checkAndCorrect(bool quiet)
       for (i=0;i<l;i++) if (diaPath.at(i)=='/') diaPath.at(i)='\\';
 #endif
     }
+    Config_updateString(DIA_PATH,diaPath);
   }
-  else // make sure the string is empty but not null!
-  {
-    diaPath="";
-  }
-  Config_updateString(DIA_PATH,diaPath);
 
   //------------------------
   // check INPUT
@@ -1974,28 +1960,6 @@ void Config::checkAndCorrect(bool quiet)
   Config_updateList(INPUT,inputSources);
 
   //------------------------
-  // add default file patterns if needed
-  StringVector filePatternList = Config_getList(FILE_PATTERNS);
-  if (filePatternList.empty())
-  {
-    ConfigOption * opt = ConfigImpl::instance()->get("FILE_PATTERNS");
-    if (opt->kind()==ConfigOption::O_List)
-    {
-      filePatternList = ((ConfigList*)opt)->getDefault();
-    }
-  }
-  Config_updateList(FILE_PATTERNS,filePatternList);
-
-  //------------------------
-  // add default pattern if needed
-  StringVector examplePatternList = Config_getList(EXAMPLE_PATTERNS);
-  if (examplePatternList.empty())
-  {
-    examplePatternList.push_back("*");
-    Config_updateList(EXAMPLE_PATTERNS,examplePatternList);
-  }
-
-  //------------------------
   // if no output format is enabled, warn the user
   if (!Config_getBool(GENERATE_HTML)    &&
       !Config_getBool(GENERATE_LATEX)   &&
@@ -2053,90 +2017,16 @@ void Config::checkAndCorrect(bool quiet)
   }
 
   //------------------------
-  int hue = Config_getInt(HTML_COLORSTYLE_HUE);
-  if (hue<0)
+  // check for settings that are inconsistent with having OPTIMIZED_OUTPUT_VHDL enabled
+  if (Config_getBool(OPTIMIZE_OUTPUT_VHDL))
   {
-    hue=0;
-  }
-  else if (hue>=360)
-  {
-    hue=hue%360;
-  }
-  Config_updateInt(HTML_COLORSTYLE_HUE,hue);
-
-  //------------------------
-  int sat = Config_getInt(HTML_COLORSTYLE_SAT);
-  if (sat<0)
-  {
-    sat=0;
-  }
-  else if (sat>255)
-  {
-    sat=255;
-  }
-  Config_updateInt(HTML_COLORSTYLE_SAT,sat);
-
-
-  //------------------------
-  int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA);
-  if (gamma<40)
-  {
-    gamma=40;
-  }
-  else if (gamma>240)
-  {
-    gamma=240;
-  }
-  Config_updateInt(HTML_COLORSTYLE_GAMMA,gamma);
-
-  //------------------------
-  // add default words if needed
-  const StringVector &annotationFromBrief = Config_getList(ABBREVIATE_BRIEF);
-  if (annotationFromBrief.empty())
-  {
-    Config_updateList(ABBREVIATE_BRIEF,
-                      { "The $name class", "The $name widget",
-                        "The $name file", "is", "provides", "specifies",
-                        "contains", "represents", "a", "an", "the"
-                      });
-  }
-
-  //------------------------
-  // some default settings for vhdl
-  if (Config_getBool(OPTIMIZE_OUTPUT_VHDL) &&
-      (Config_getBool(INLINE_INHERITED_MEMB) ||
-       Config_getBool(INHERIT_DOCS) ||
-       !Config_getBool(HIDE_SCOPE_NAMES) ||
-       !Config_getBool(EXTRACT_PRIVATE) ||
-       !Config_getBool(EXTRACT_PACKAGE)
-      )
-     )
-  {
-    bool b1 = Config_getBool(INLINE_INHERITED_MEMB);
-    bool b2 = Config_getBool(INHERIT_DOCS);
-    bool b3 = Config_getBool(HIDE_SCOPE_NAMES);
-    bool b4 = Config_getBool(EXTRACT_PRIVATE);
-    bool b5 = Config_getBool(SKIP_FUNCTION_MACROS);
-    bool b6 = Config_getBool(EXTRACT_PACKAGE);
-    const char *s1,*s2,*s3,*s4,*s5,*s6;
-    if (b1)  s1="  INLINE_INHERITED_MEMB  = NO (was YES)\n"; else s1="";
-    if (b2)  s2="  INHERIT_DOCS           = NO (was YES)\n"; else s2="";
-    if (!b3) s3="  HIDE_SCOPE_NAMES       = YES (was NO)\n"; else s3="";
-    if (!b4) s4="  EXTRACT_PRIVATE        = YES (was NO)\n"; else s4="";
-    if (b5)  s5="  ENABLE_PREPROCESSING   = NO (was YES)\n"; else s5="";
-    if (!b6) s6="  EXTRACT_PACKAGE        = YES (was NO)\n"; else s6="";
-
-
-    warn_uncond("enabling OPTIMIZE_OUTPUT_VHDL assumes the following settings:\n"
-               "%s%s%s%s%s%s",s1,s2,s3,s4,s5,s6
-              );
-
-    Config_updateBool(INLINE_INHERITED_MEMB, FALSE);
-    Config_updateBool(INHERIT_DOCS,          FALSE);
-    Config_updateBool(HIDE_SCOPE_NAMES,      TRUE);
-    Config_updateBool(EXTRACT_PRIVATE,       TRUE);
-    Config_updateBool(ENABLE_PREPROCESSING,  FALSE);
-    Config_updateBool(EXTRACT_PACKAGE,       TRUE);
+    const char *depOption = "OPTIMIZE_OUTPUT_VHDL";
+    adjustBoolSetting(depOption,"INLINE_INHERITED_MEMB",false);
+    adjustBoolSetting(depOption,"INHERIT_DOCS",         false);
+    adjustBoolSetting(depOption,"HIDE_SCOPE_NAMES",     true );
+    adjustBoolSetting(depOption,"EXTRACT_PRIVATE",      true );
+    adjustBoolSetting(depOption,"ENABLE_PREPROCESSING", false);
+    adjustBoolSetting(depOption,"EXTRACT_PACKAGE",      true );
   }
 
   if (!checkFileName(Config_getString(GENERATE_TAGFILE),"GENERATE_TAGFILE"))
@@ -2166,7 +2056,36 @@ void Config::checkAndCorrect(bool quiet)
   }
 #endif
 
+}
 
+void Config::updateObsolete()
+{
+  //------------------------
+  // check for presence of obsolete CLASS_DIAGRAM option and correct CLASS_GRAPH if needed
+  ConfigOption *classDiagramsOpt = ConfigImpl::instance()->get("CLASS_DIAGRAMS");
+  ConfigOption *haveDotOpt       = ConfigImpl::instance()->get("HAVE_DOT");
+  ConfigOption *classGraphOpt    = ConfigImpl::instance()->get("CLASS_GRAPH");
+  if (classDiagramsOpt && classDiagramsOpt->kind()==ConfigOption::O_Obsolete &&
+      haveDotOpt && classGraphOpt)
+  {
+    ConfigObsolete *classDiagramsOpt_ = dynamic_cast<ConfigObsolete*>(classDiagramsOpt);
+    ConfigBool     *haveDotOpt_       = dynamic_cast<ConfigBool*>(haveDotOpt);
+    ConfigEnum     *classGraphOpt_    = dynamic_cast<ConfigEnum*>(classGraphOpt);
+    if (classDiagramsOpt_->isPresent() && classDiagramsOpt_->orgType()==ConfigOption::O_Bool)
+    {
+      QCString classDiagramValue = *classDiagramsOpt_->valueStringRef();
+      QCString haveDotValue      = *haveDotOpt_->valueStringRef();
+      QCString &classGraphValue  = *classGraphOpt_->valueRef();
+      bool isValid1=true, isValid2=true;
+      bool bClassDiagrams = convertStringToBool(classDiagramValue,isValid1);
+      bool bHaveDot       = haveDotValue.isEmpty() ? false : convertStringToBool(haveDotValue,     isValid2);
+      if (isValid1 && isValid2 && !bClassDiagrams && !bHaveDot && classGraphValue.lower()=="yes")
+      {
+        warn_uncond("Changing CLASS_GRAPH option to TEXT because obsolete option CLASS_DIAGRAM was found and set to NO.\n");
+        classGraphValue="TEXT";
+      }
+    }
+  }
 }
 
 void Config::writeTemplate(TextStream &t,bool shortList,bool update)
@@ -2194,6 +2113,7 @@ bool Config::parse(const QCString &fileName,bool update)
   // when updating etc. the output is in this format as well and not in the read format
   ConfigString *option = (ConfigString*)g_config->get("DOXYFILE_ENCODING");
   option->init();
+
   return parseRes;
 }
 
index 889626c..7382528 100644 (file)
 %option extra-type="struct constexpYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve typesafety
+#include "constexp_p.h"  
 }
 
 %{
 
 #include "constexp.h"  
-#include "constexp_p.h"  
 #include "cppvalue.h"
 #include "ce_parse.hpp" // generated header file
 #include "message.h"
@@ -46,6 +47,11 @@ static yy_size_t yyread(char *buf,yy_size_t max_size,yyscan_t yyscanner);
 #undef  YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#define LEX_NO_INPUT_FILENAME
+#include "doxygen_lex.h"
+
 %}
 
 CONSTSUFFIX ([uU][lL]?[lL]?)|([lL][lL]?[uU]?)
index 4ce94bc..94da6ce 100644 (file)
 
 #include "cppvalue.h"
 #define YYSTYPE CPPValue
+#define YY_TYPEDEF_YY_SCANNER_T
 
-typedef void* yyscan_t;
+struct yyguts_t;
+typedef yyguts_t* yyscan_t;
 struct constexpYY_state
 {
   std::string  strToken;
index a84f77a..6274ce6 100644 (file)
@@ -78,37 +78,77 @@ struct ContextGlobals
   ContextOutputFormat outputFormat;
 } g_globals;
 
-/** @brief Reference counting smart pointer */
-template<class T> class SharedPtr
+
+/** Wrapper for data that needs to be cached.
+ *  The cached data can be accessed via the get() method from multiple threads.
+ *  The first thread that calls get() will trigger creation of the data item via
+ *  the creator method, blocking other threads until the item is available in the cache.
+ *  @tparam T       the type of the data item in the cache.
+ *  @tparam TOwner  the class containing the cached item.
+ *  @tparam creator the method of TOwner to call in order to create the data item to be cached.
+ */
+template<typename T, typename TOwner, T(TOwner::*creator)() const>
+class CachedItem
 {
+  public:
+    /** Returns a reference to the cached data.
+     *  Conceptually this is a const method, i.e. it will always return the same data
+     *  The first time it is called, the owner will be asked to create the data.
+     */
+    T &get(const TOwner *owner) const
+    {
+      // create a lamda function to create the cached data
+      auto creatorFunc = [this,owner]() { m_item = (owner->*creator)(); };
+      // use std::call_once to let one thread invoke the creator func
+      std::call_once(m_cache_flag, creatorFunc);
+      // return the cached results
+      return m_item;
+    }
   private:
-    T *m_ptr;
-    SharedPtr(const SharedPtr &);
-    SharedPtr &operator=(const SharedPtr &p);
-    void operator==(const SharedPtr &) const;
-    void operator!=(const SharedPtr &) const;
+    mutable std::once_flag m_cache_flag; // flag to keep track if the item is already cached
+    mutable T              m_item;       // the cached data item
+};
+
+//------------------------------------------------------------------------
 
+/** Class representing a mapping of properties and the corresponding getter function.
+ *  The map should be initialized at initialization time.
+ */
+template<class T>
+class PropertyMap
+{
   public:
-    typedef T Type;
-    explicit SharedPtr(T *p=0) : m_ptr(p) { if (m_ptr) m_ptr->addRef(); }
-    ~SharedPtr() { if (m_ptr) m_ptr->release(); };
-    T &operator*() const { return *m_ptr; }
-    T *operator->() const { return m_ptr; }
-    T *get() const { return m_ptr; }
-    operator bool() const { return m_ptr!=0; }
-    void reset(T *p=0)
-    {
-      if (p) p->addRef();
-      if (m_ptr) m_ptr->release();
-      m_ptr = p;
+    using Map = std::map< std::string, TemplateVariant(T::*)() const >;
+
+    PropertyMap(std::initializer_list<typename Map::value_type> init)
+      : m_map(init) {}
+
+    TemplateVariant get(const T *obj,const QCString &n) const
+    {
+      auto it = m_map.find(n.str());
+      return it!=m_map.end() ? (obj->*(it->second))() : TemplateVariant();
+    }
+    StringVector fields() const
+    {
+      StringVector result;
+      result.reserve(m_map.size());
+      for (const auto &imap : m_map) result.push_back(imap.first);
+      return result;
     }
+
+    Map &map() { return m_map; }
+
+  private:
+    const Map m_map;
 };
 
+//------------------------------------------------------------------------
+
 /** @brief Template List iterator support */
 class GenericConstIterator : public TemplateListIntf::ConstIterator
 {
   public:
-    GenericConstIterator(const std::vector<TemplateVariant> &list) : m_list(list) {}
+    GenericConstIterator(const TemplateVariantList &list) : m_list(list) {}
     virtual ~GenericConstIterator() {}
     void toFirst()
     {
@@ -140,7 +180,7 @@ class GenericConstIterator : public TemplateListIntf::ConstIterator
       }
     }
   private:
-    const std::vector<TemplateVariant> &m_list;
+    const TemplateVariantList &m_list;
     int m_index=0;
 };
 
@@ -150,12 +190,12 @@ class GenericConstIterator : public TemplateListIntf::ConstIterator
 class GenericNodeListContext : public TemplateListIntf
 {
   public:
-    GenericNodeListContext() : m_refCount(0)
+    GenericNodeListContext()
     {
     }
-    static GenericNodeListContext *alloc()
+    static TemplateListIntfPtr alloc()
     {
-      return new GenericNodeListContext;
+      return std::static_pointer_cast<TemplateListIntf>(std::make_shared<GenericNodeListContext>());
     }
 
     // TemplateListIntf methods
@@ -172,9 +212,9 @@ class GenericNodeListContext : public TemplateListIntf
       }
       return result;
     }
-    TemplateListIntf::ConstIterator *createIterator() const
+    TemplateListIntf::ConstIteratorPtr createIterator() const
     {
-      return new GenericConstIterator(m_children);
+      return std::make_unique<GenericConstIterator>(m_children);
     }
 
     void append(const TemplateVariant &ctn)
@@ -185,253 +225,156 @@ class GenericNodeListContext : public TemplateListIntf
     {
       return m_children.empty();
     }
-    int addRef()
-    {
-      return ++m_refCount;
-    }
-    int release()
-    {
-      int count = --m_refCount;
-      if (count<=0)
-      {
-        delete this;
-      }
-      return count;
-    }
   private:
     std::vector< TemplateVariant > m_children;
-    int m_refCount;
 };
 
 //------------------------------------------------------------------------
 
-/** @brief Helper class to map a property name to a handler member function */
-template<typename T>
-class PropertyMapper
+//%% struct Config : configuration options
+//%% {
+class ConfigContext::Private
 {
-  private:
-    struct PropertyFuncIntf
-    {
-      virtual ~PropertyFuncIntf() {}
-      virtual TemplateVariant operator()(const T *obj) const = 0;
-    };
-    struct PropertyFunc : public PropertyFuncIntf
-    {
-      typedef TemplateVariant (T::*Handler)() const;
-      PropertyFunc(Handler h) : handler(h) {}
-      TemplateVariant operator()(const T *obj) const
-      {
-        return (obj->*handler)();
-      }
-      Handler handler;
-    };
-
   public:
-    /** Add a property to the map
-     *  @param[in] name   The name of the property to add.
-     *  @param[in] handle The method to call when the property is accessed.
-     */
-    void addProperty(const char *name,typename PropertyFunc::Handler handle)
-    {
-      auto it = m_map.find(name);
-      if (it!=m_map.end())
-      {
-        err("adding property '%s' more than once\n",name);
-      }
-      else
-      {
-        m_map.insert(std::make_pair(name,std::make_unique<PropertyFunc>(handle)));
-      }
-    }
-
-    /** Gets the value of a property.
-     *  @param[in] obj  The object handling access to the property.
-     *  @param[in] name The name of the property.
-     *  @returns A variant representing the properties value or an
-     *  invalid variant if it was not found.
-     */
-    TemplateVariant get(const T *obj,const QCString &name) const
+    // TemplateStructIntf methods
+    StringVector fields() const
     {
-      //printf("PropertyMapper::get(%s)\n",name);
-      TemplateVariant result;
-      auto it = m_map.find(name.str());
-      return it!=m_map.end() ? (*it->second)(obj) : TemplateVariant();
+      return m_fields.get(this);
     }
-
-    StringVector fields() const
+    TemplateVariant get(const QCString &name) const
     {
-      StringVector result;
-      for (const auto &kv : m_map)
-      {
-        result.push_back(kv.first);
-      }
-      std::sort(result.begin(),result.end());
-      return result;
+      auto &data = m_configData.get(this);
+      auto it = data.find(name.str());
+      return (it!=data.end()) ? it->second : TemplateVariant();
     }
-
   private:
-    std::unordered_map<std::string,std::unique_ptr<PropertyFuncIntf>> m_map;
-};
-
-
-//------------------------------------------------------------------------
+    using ConfigData = std::map<std::string,TemplateVariant>;
 
-//%% struct Config : configuration options
-//%% {
-class ConfigContext::Private
-{
-  public:
-    Private() { }
-    virtual ~Private() { }
-    TemplateVariant fetchList(const QCString &name,const StringVector &list)
+    ConfigData createConfigData() const
     {
-      auto it = m_cachedLists.find(name.str());
-      if (it==m_cachedLists.end())
+      std::map<std::string,TemplateVariant> map;
+      for (auto name : ConfigValues::instance().fields())
       {
-        TemplateList *tlist = TemplateList::alloc();
-        m_cachedLists.insert(std::make_pair(name.str(),TemplateVariant(tlist)));
-        for (const auto &s : list)
+        const ConfigValues::Info *option = ConfigValues::instance().get(QCString(name));
+        if (option)
         {
-          tlist->append(s.c_str());
+          switch (option->type)
+          {
+            case ConfigValues::Info::Bool:
+              {
+                bool b = ConfigValues::instance().*(option->value.b);
+                map.insert(std::make_pair(name,TemplateVariant(b)));
+              }
+              break;
+            case ConfigValues::Info::Int:
+              {
+                int i = ConfigValues::instance().*(option->value.i);
+                map.insert(std::make_pair(name,TemplateVariant(i)));
+              }
+              break;
+            case ConfigValues::Info::String:
+              {
+                QCString s = ConfigValues::instance().*(option->value.s);
+                map.insert(std::make_pair(name,TemplateVariant(s)));
+              }
+              break;
+            case ConfigValues::Info::List:
+              {
+                auto fetchList = [](const StringVector &list) -> TemplateVariant
+                {
+                  TemplateVariantList elements;
+                  elements.reserve(list.size());
+                  for (const auto &s : list)
+                  {
+                    elements.push_back(TemplateVariant(s));
+                  }
+                  return TemplateImmutableList::alloc(elements);
+                };
+                const StringVector &l = ConfigValues::instance().*(option->value.l);
+                map.insert(std::make_pair(name,fetchList(l)));
+              }
+              break;
+            default:
+              break;
+          }
         }
-        return tlist;
-      }
-      else
-      {
-        return it->second;
       }
+      return map;
     }
-  private:
-    std::unordered_map<std::string,TemplateVariant> m_cachedLists;
+
+    StringVector createFields() const
+    {
+      return ConfigValues::instance().fields();
+    }
+
+    CachedItem<StringVector, Private, &Private::createFields    > m_fields;
+    CachedItem<ConfigData,   Private, &Private::createConfigData> m_configData;
 };
 //%% }
 
-ConfigContext::ConfigContext() : RefCountedContext("ConfigContext")
+ConfigContext::ConfigContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 ConfigContext::~ConfigContext()
 {
-  delete p;
 }
 
 TemplateVariant ConfigContext::get(const QCString &name) const
 {
-  TemplateVariant result;
-  if (!name.isEmpty())
-  {
-    const ConfigValues::Info *option = ConfigValues::instance().get(name);
-    if (option)
-    {
-      switch (option->type)
-      {
-        case ConfigValues::Info::Bool:
-          {
-            bool b = ConfigValues::instance().*(option->value.b);
-            return TemplateVariant(b);
-          }
-        case ConfigValues::Info::Int:
-          {
-            int i = ConfigValues::instance().*(option->value.i);
-            return TemplateVariant(i);
-          }
-        case ConfigValues::Info::String:
-          {
-            QCString s = ConfigValues::instance().*(option->value.s);
-            return TemplateVariant(s);
-          }
-        case ConfigValues::Info::List:
-          {
-            const StringVector &l = ConfigValues::instance().*(option->value.l);
-            return p->fetchList(name,l);
-          }
-        default:
-          break;
-      }
-    }
-  }
-  return result;
+  return p->get(name);
 }
 
 StringVector ConfigContext::fields() const
 {
-  return ConfigValues::instance().fields();
+  return p->fields();
 }
 
 //------------------------------------------------------------------------
 
-//%% struct Doxygen: global information
-//%% {
 class DoxygenContext::Private
 {
   public:
-    TemplateVariant version() const
-    {
-      return getDoxygenVersion();
-    }
-    TemplateVariant date() const
-    {
-      return dateToString(TRUE);
-    }
-    TemplateVariant mathJaxCodeFile() const
-    {
-      return m_cache.mathJaxCodeFile;
-    }
-    TemplateVariant mathJaxMacros() const
-    {
-      return m_cache.mathJaxMacros;
-    }
-    Private()
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        //%% string version
-        s_inst.addProperty("version",         &Private::version);
-        //%% string date
-        s_inst.addProperty("date",            &Private::date);
-        //%% string maxJaxCodeFile
-        s_inst.addProperty("mathJaxCodeFile", &Private::mathJaxCodeFile);
-        //%% string maxJaxMacros
-        s_inst.addProperty("mathJaxMacros",   &Private::mathJaxMacros);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
   private:
-    struct Cachable
-    {
-      Cachable() {
-        mathJaxCodeFile=fileToString(Config_getString(MATHJAX_CODEFILE));
-        mathJaxMacros=HtmlGenerator::getMathJaxMacros();
-      }
-      QCString mathJaxCodeFile;
-      QCString mathJaxMacros;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<DoxygenContext::Private> s_inst;
+    // Property getters
+    TemplateVariant version() const         { return getDoxygenVersion(); }
+    TemplateVariant date() const            { return dateToString(TRUE); }
+    TemplateVariant mathJaxCodeFile() const { return m_mathJaxCodeFile.get(this); }
+    TemplateVariant mathJaxMacros() const   { return m_mathJaxMacros.get(this); }
+
+  private:
+    QCString createMathJaxCodeFile() const { return fileToString(Config_getString(MATHJAX_CODEFILE)); }
+    QCString createMathJaxMacros() const   { return HtmlGenerator::getMathJaxMacros(); }
+    CachedItem<QCString, Private, &Private::createMathJaxCodeFile> m_mathJaxCodeFile;
+    CachedItem<QCString, Private, &Private::createMathJaxMacros>   m_mathJaxMacros;
+    static const PropertyMap<DoxygenContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<DoxygenContext::Private> DoxygenContext::Private::s_inst;
-//                                (PropertyMapper<DoxygenContext::Private>::instance());
+//%% struct Doxygen: global information
+//%% {
+const PropertyMap<DoxygenContext::Private> DoxygenContext::Private::s_inst {
+{
+  //%% string version
+  { "version",         &Private::version         },
+  //%% string date
+  { "date",            &Private::date            },
+  //%% string maxJaxCodeFile
+  { "mathJaxCodeFile", &Private::mathJaxCodeFile },
+  //%% string maxJaxMacros
+  { "mathJaxMacros",   &Private::mathJaxMacros   }
+} };
+//%% }
 
-DoxygenContext::DoxygenContext() : RefCountedContext("DoxygenContext")
+DoxygenContext::DoxygenContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 DoxygenContext::~DoxygenContext()
 {
-  delete p;
 }
 
 TemplateVariant DoxygenContext::get(const QCString &n) const
@@ -446,13 +389,25 @@ StringVector DoxygenContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct Translator: translation methods
-//%% {
 class TranslateContext::Private
 {
   public:
 
-    TemplateVariant handleGeneratedAt(const std::vector<TemplateVariant> &args) const
+    Private()
+    {
+      m_javaOpt    = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
+      m_fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
+      m_vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
+      m_sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+    }
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+  private:
+
+    // Handlers for properties with parameters
+    TemplateVariant handleGeneratedAt(const TemplateVariantList &args) const
     {
       if (args.size()==2)
       {
@@ -464,7 +419,7 @@ class TranslateContext::Private
       }
       return TemplateVariant();
     }
-    TemplateVariant handleInheritanceDiagramFor(const std::vector<TemplateVariant> &args) const
+    TemplateVariant handleInheritanceDiagramFor(const TemplateVariantList &args) const
     {
       if (args.size()==1)
       {
@@ -476,7 +431,7 @@ class TranslateContext::Private
       }
       return TemplateVariant();
     }
-    TemplateVariant handleCollaborationDiagramFor(const std::vector<TemplateVariant> &args) const
+    TemplateVariant handleCollaborationDiagramFor(const TemplateVariantList &args) const
     {
       if (args.size()==1)
       {
@@ -488,7 +443,7 @@ class TranslateContext::Private
       }
       return TemplateVariant();
     }
-    TemplateVariant handleDirDependencyGraphFor(const std::vector<TemplateVariant> &args) const
+    TemplateVariant handleDirDependencyGraphFor(const TemplateVariantList &args) const
     {
       if (args.size()==1)
       {
@@ -500,7 +455,7 @@ class TranslateContext::Private
       }
       return TemplateVariant();
     }
-    TemplateVariant handleInheritsList(const std::vector<TemplateVariant> &args) const
+    TemplateVariant handleInheritsList(const TemplateVariantList &args) const
     {
       if (args.size()==1)
       {
@@ -512,7 +467,7 @@ class TranslateContext::Private
       }
       return TemplateVariant();
     }
-    TemplateVariant handleInheritedByList(const std::vector<TemplateVariant> &args) const
+    TemplateVariant handleInheritedByList(const TemplateVariantList &args) const
     {
       if (args.size()==1)
       {
@@ -524,7 +479,7 @@ class TranslateContext::Private
       }
       return TemplateVariant();
     }
-    TemplateVariant handleWriteList(const std::vector<TemplateVariant> &args) const
+    TemplateVariant handleWriteList(const TemplateVariantList &args) const
     {
       if (args.size()==1)
       {
@@ -536,7 +491,7 @@ class TranslateContext::Private
       }
       return TemplateVariant();
     }
-    TemplateVariant handleImplementedBy(const std::vector<TemplateVariant> &args) const
+    TemplateVariant handleImplementedBy(const TemplateVariantList &args) const
     {
       if (args.size()==1)
       {
@@ -548,7 +503,7 @@ class TranslateContext::Private
       }
       return TemplateVariant();
     }
-    TemplateVariant handleReimplementedBy(const std::vector<TemplateVariant> &args) const
+    TemplateVariant handleReimplementedBy(const TemplateVariantList &args) const
     {
       if (args.size()==1)
       {
@@ -560,7 +515,7 @@ class TranslateContext::Private
       }
       return TemplateVariant();
     }
-    TemplateVariant handleSourceRefs(const std::vector<TemplateVariant> &args) const
+    TemplateVariant handleSourceRefs(const TemplateVariantList &args) const
     {
       if (args.size()==1)
       {
@@ -572,7 +527,7 @@ class TranslateContext::Private
       }
       return TemplateVariant();
     }
-    TemplateVariant handleSourceRefBys(const std::vector<TemplateVariant> &args) const
+    TemplateVariant handleSourceRefBys(const TemplateVariantList &args) const
     {
       if (args.size()==1)
       {
@@ -584,7 +539,7 @@ class TranslateContext::Private
       }
       return TemplateVariant();
     }
-    TemplateVariant handleIncludeDependencyGraph(const std::vector<TemplateVariant> &args) const
+    TemplateVariant handleIncludeDependencyGraph(const TemplateVariantList &args) const
     {
       if (args.size()==1)
       {
@@ -597,27 +552,26 @@ class TranslateContext::Private
       return TemplateVariant();
     }
 
-
-
+    // Property getters
     TemplateVariant generatedBy() const
     {
       return theTranslator->trGeneratedBy();
     }
     TemplateVariant generatedAt() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleGeneratedAt>(this);
+      return TemplateVariant(std::bind(&Private::handleGeneratedAt,this,std::placeholders::_1));
     }
     TemplateVariant inheritanceDiagramFor() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleInheritanceDiagramFor>(this);
+      return TemplateVariant(std::bind(&Private::handleInheritanceDiagramFor,this,std::placeholders::_1));
     }
     TemplateVariant collaborationDiagramFor() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleCollaborationDiagramFor>(this);
+      return TemplateVariant(std::bind(&Private::handleCollaborationDiagramFor,this,std::placeholders::_1));
     }
     TemplateVariant dirDependencyGraphFor() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleDirDependencyGraphFor>(this);
+      return TemplateVariant(std::bind(&Private::handleDirDependencyGraphFor,this,std::placeholders::_1));
     }
     TemplateVariant search() const
     {
@@ -799,11 +753,11 @@ class TranslateContext::Private
     }
     TemplateVariant inheritsList() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleInheritsList>(this);
+      return TemplateVariant(std::bind(&Private::handleInheritsList,this,std::placeholders::_1));
     }
     TemplateVariant inheritedByList() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleInheritedByList>(this);
+      return TemplateVariant(std::bind(&Private::handleInheritedByList,this,std::placeholders::_1));
     }
     TemplateVariant definedAtLineInSourceFile() const
     {
@@ -815,7 +769,7 @@ class TranslateContext::Private
     }
     TemplateVariant exampleList() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleWriteList>(this);
+      return TemplateVariant(std::bind(&Private::handleWriteList,this,std::placeholders::_1));
     }
     TemplateVariant listOfAllMembers() const
     {
@@ -855,19 +809,19 @@ class TranslateContext::Private
     }
     TemplateVariant implementedBy() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleImplementedBy>(this);
+      return TemplateVariant(std::bind(&Private::handleImplementedBy,this,std::placeholders::_1));
     }
     TemplateVariant reimplementedBy() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleReimplementedBy>(this);
+      return TemplateVariant(std::bind(&Private::handleReimplementedBy,this,std::placeholders::_1));
     }
     TemplateVariant sourceRefs() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleSourceRefs>(this);
+      return TemplateVariant(std::bind(&Private::handleSourceRefs,this,std::placeholders::_1));
     }
     TemplateVariant sourceRefBys() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleSourceRefBys>(this);
+      return TemplateVariant(std::bind(&Private::handleSourceRefBys,this,std::placeholders::_1));
     }
     TemplateVariant callGraph() const
     {
@@ -895,7 +849,7 @@ class TranslateContext::Private
     }
     TemplateVariant includeDependencyGraph() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleIncludeDependencyGraph>(this);
+      return TemplateVariant(std::bind(&Private::handleIncludeDependencyGraph,this,std::placeholders::_1));
     }
     TemplateVariant includedByDependencyGraph() const
     {
@@ -1050,245 +1004,226 @@ class TranslateContext::Private
     {
       return theTranslator->trCode();
     }
-    Private()
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        //%% string generatedBy
-        s_inst.addProperty("generatedBy",       &Private::generatedBy);
-        //%% string generatedAt
-        s_inst.addProperty("generatedAt",       &Private::generatedAt);
-        //%% string search
-        s_inst.addProperty("search",            &Private::search);
-        //%% string mainPage
-        s_inst.addProperty("mainPage",          &Private::mainPage);
-        //%% string classes
-        s_inst.addProperty("classes",           &Private::classes);
-        //%% string classList
-        s_inst.addProperty("classList",         &Private::classList);
-        //%% string classListDescription
-        s_inst.addProperty("classListDescription", &Private::classListDescription);
-        //%% string classIndex
-        s_inst.addProperty("classIndex",        &Private::classIndex);
-        //%% string concepts
-        s_inst.addProperty("concepts",          &Private::concepts);
-        //%% string conceptDefintion
-        s_inst.addProperty("conceptDefinition", &Private::conceptDefinition);
-        //%% string namespaceIndex
-        s_inst.addProperty("namespaceIndex",    &Private::namespaceIndex);
-        //%% string classHierarchy
-        s_inst.addProperty("classHierarchy",    &Private::classHierarchy);
-        //%% string classMembers
-        s_inst.addProperty("classMembers",      &Private::classMembers);
-        //%% string classMembersDescription
-        s_inst.addProperty("classMembersDescription",&Private::classMembersDescription);
-        //%% string modules
-        s_inst.addProperty("modules",           &Private::modules);
-        //%% string moduleIndex
-        s_inst.addProperty("moduleIndex",       &Private::moduleIndex);
-        //%% string namespaces
-        s_inst.addProperty("namespaces",        &Private::namespaces);
-        //%% string fileIndex
-        s_inst.addProperty("fileIndex",         &Private::fileIndex);
-        //%% string files
-        s_inst.addProperty("files",             &Private::files);
-        //%% string pages
-        s_inst.addProperty("pages",             &Private::pages);
-        //%% string examples
-        s_inst.addProperty("examples",          &Private::examples);
-        //%% string namespaceList
-        s_inst.addProperty("namespaceList",     &Private::namespaceList);
-        //%% string namespaceMembers
-        s_inst.addProperty("namespaceMembers",  &Private::namespaceMembers);
-        //%% string fileList
-        s_inst.addProperty("fileList",          &Private::fileList);
-        //%% string fileMembers
-        s_inst.addProperty("fileMembers",       &Private::fileMembers);
-        //%% string fileMembersDescription
-        s_inst.addProperty("fileMembersDescription", &Private::fileMembersDescription);
-        //%% string relatedPagesDescription
-        s_inst.addProperty("relatedPagesDesc",  &Private::relatedPagesDesc);
-        //%% string more
-        s_inst.addProperty("more",              &Private::more);
-        //%% string detailedDescription
-        s_inst.addProperty("detailedDesc",      &Private::detailedDesc);
-        //%% string inheritanceDiagramFor
-        s_inst.addProperty("inheritanceDiagramFor", &Private::inheritanceDiagramFor);
-        //%% string collaborationDiagramFor
-        s_inst.addProperty("collaborationDiagramFor", &Private::collaborationDiagramFor);
-        //%% markerstring inheritsList
-        s_inst.addProperty("inheritsList",      &Private::inheritsList);
-        //%% markerstring inheritedByList
-        s_inst.addProperty("inheritedByList",   &Private::inheritedByList);
-        //%% markerstring definedAtLineInSourceFile
-        s_inst.addProperty("definedAtLineInSourceFile", &Private::definedAtLineInSourceFile);
-        //%% string typeConstraints
-        s_inst.addProperty("typeConstraints",   &Private::typeConstraints);
-        //%% string exampleList
-        s_inst.addProperty("exampleList",       &Private::exampleList);
-        //%% string listOfAllMembers
-        s_inst.addProperty("listOfAllMembers",  &Private::listOfAllMembers);
-        //%% string memberList
-        s_inst.addProperty("memberList",        &Private::memberList);
-        //%% string theListOfAllMembers
-        s_inst.addProperty("theListOfAllMembers",&Private::theListOfAllMembers);
-        //%% string incInheritedMembers
-        s_inst.addProperty("incInheritedMembers",&Private::incInheritedMembers);
-        //%% string defineValue
-        s_inst.addProperty("defineValue",        &Private::defineValue);
-        //%% string initialValue
-        s_inst.addProperty("initialValue",       &Private::initialValue);
-        //%% markerstring implements
-        s_inst.addProperty("implements",         &Private::implements);
-        //%% markerstring reimplements
-        s_inst.addProperty("reimplements",       &Private::reimplements);
-        //%% markerstring implementedBy
-        s_inst.addProperty("implementedBy",      &Private::implementedBy);
-        //%% markerstring reimplementedBy
-        s_inst.addProperty("reimplementedBy",    &Private::reimplementedBy);
-        //%% markerstring sourceRefs
-        s_inst.addProperty("sourceRefs",         &Private::sourceRefs);
-        //%% markerstring sourceRefBys
-        s_inst.addProperty("sourceRefBys",       &Private::sourceRefBys);
-        //%% string callGraph
-        s_inst.addProperty("callGraph",          &Private::callGraph);
-        //%% string callerGraph
-        s_inst.addProperty("callerGraph",        &Private::callerGraph);
-        //%% string referencedByRelation
-        s_inst.addProperty("referencedByRelation", &Private::referencedByRelation);
-        //%% string referencesRelation
-        s_inst.addProperty("referencesRelation",   &Private::referencesRelation);
-        //%% markerstring inheritedFrom
-        s_inst.addProperty("inheritedFrom",      &Private::inheritedFrom);
-        //%% string additionalInheritedMembers
-        s_inst.addProperty("additionalInheritedMembers",&Private::additionalInheritedMembers);
-        //%% string includeDependencyGraph:container_name
-        s_inst.addProperty("includeDependencyGraph",&Private::includeDependencyGraph);
-        //%% string includedByDependencyGraph
-        s_inst.addProperty("includedByDependencyGraph",&Private::includedByDependencyGraph);
-        //%% string gotoSourceCode
-        s_inst.addProperty("gotoSourceCode",     &Private::gotoSourceCode);
-        //%% string gotoDocumentation
-        s_inst.addProperty("gotoDocumentation",  &Private::gotoDocumentation);
-        //%% string constantgroups
-        s_inst.addProperty("constantgroups",     &Private::constantgroups);
-        //%% string classDocumentation
-        s_inst.addProperty("classDocumentation", &Private::classDocumentation);
-        //%% string namespaceDocumentation
-        s_inst.addProperty("namespaceDocumentation", &Private::namespaceDocumentation);
-        //%% string moduleDocumentation
-        s_inst.addProperty("moduleDocumentation",&Private::moduleDocumentation);
-        //%% string fileDocumentation
-        s_inst.addProperty("fileDocumentation",  &Private::fileDocumentation);
-        //%% string compoundMembers
-        s_inst.addProperty("compoundMembers",    &Private::compoundMembers);
-        //%% string detailLevel
-        s_inst.addProperty("detailLevel",        &Private::detailLevel);
-        //%% string fileListDescription
-        s_inst.addProperty("fileListDescription",&Private::fileListDescription);
-        //%% string namespaceListDescription
-        s_inst.addProperty("namespaceListDescription",&Private::namespaceListDescription);
-        //%% string conceptListDescription
-        s_inst.addProperty("conceptListDescription",&Private::conceptListDescription);
-        //%% string directories
-        s_inst.addProperty("directories",        &Private::directories);
-        //%% string moduleDescription
-        s_inst.addProperty("modulesDescription", &Private::modulesDescription);
-        //%% string all
-        s_inst.addProperty("all",                &Private::all);
-        //%% string functions
-        s_inst.addProperty("functions",          &Private::functions);
-        //%% string variables
-        s_inst.addProperty("variables",          &Private::variables);
-        //%% string typedefs
-        s_inst.addProperty("typedefs",           &Private::typedefs);
-        //%% string enums
-        s_inst.addProperty("enums",              &Private::enums);
-        //%% string enumValues
-        s_inst.addProperty("enumValues",         &Private::enumerationValues);
-        //%% string properties
-        s_inst.addProperty("properties",         &Private::properties);
-        //%% string events
-        s_inst.addProperty("events",             &Private::events);
-        //%% string related
-        s_inst.addProperty("related",            &Private::related);
-        //%% string macros
-        s_inst.addProperty("macros",             &Private::macros);
-        //%% string namespaceMembersDescription
-        s_inst.addProperty("namespaceMembersDescription",&Private::namespaceMembersDescription);
-        //%% string classHierarchyDescription
-        s_inst.addProperty("classHierarchyDescription",&Private::classHierarchyDescription);
-        //%% string gotoGraphicalHierarchy
-        s_inst.addProperty("gotoGraphicalHierarchy",&Private::gotoGraphicalHierarchy);
-        //%% string gotoTextualHierarchy
-        s_inst.addProperty("gotoTextualHierarchy",&Private::gotoTextualHierarchy);
-        //%% string loading
-        s_inst.addProperty("loading",            &Private::loading);
-        //%% string searching
-        s_inst.addProperty("searching",          &Private::searching);
-        //%% string noMatches
-        s_inst.addProperty("noMatches",          &Private::noMatches);
-        //%% string enumValue
-        s_inst.addProperty("enumValue",          &Private::enumValue);
-        //%% string enumName
-        s_inst.addProperty("enumName",           &Private::enumName);
-        //%% string referenceManual
-        s_inst.addProperty("referenceManual",    &Private::referenceManual);
-        //%% string index
-        s_inst.addProperty("index",              &Private::index);
-        //%% string panelSyncOn
-        s_inst.addProperty("panelSyncOn",        &Private::panelSyncOn);
-        //%% string panelSyncOff
-        s_inst.addProperty("panelSyncOff",       &Private::panelSyncOff);
-        //%% string dirDependencyGraph
-        s_inst.addProperty("dirDependencyGraphFor", &Private::dirDependencyGraphFor);
-        //%% string providedByCategory
-        s_inst.addProperty("providedByCategory", &Private::providedByCategory);
-        //%% string extendsClass
-        s_inst.addProperty("extendsClass",       &Private::extendsClass);
-        //%% string examplesDescription
-        s_inst.addProperty("examplesDescription",&Private::examplesDescription);
-        //%% string langstring
-        s_inst.addProperty("langString",         &Private::langString);
-        //%% string code
-        s_inst.addProperty("code",               &Private::code);
-
-        init=TRUE;
-      }
 
-      m_javaOpt    = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
-      m_fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
-      m_vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
-      m_sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
   private:
     bool m_javaOpt;
     bool m_fortranOpt;
     bool m_vhdlOpt;
     bool m_sliceOpt;
-    static PropertyMapper<TranslateContext::Private> s_inst;
+    static const PropertyMap<TranslateContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<TranslateContext::Private> TranslateContext::Private::s_inst;
+//%% struct Translator: translation methods
+//%% {
+const PropertyMap<TranslateContext::Private> TranslateContext::Private::s_inst {
+{
+  //%% string generatedBy
+  {  "generatedBy",       &Private::generatedBy },
+  //%% string generatedAt
+  {  "generatedAt",       &Private::generatedAt },
+  //%% string search
+  {  "search",            &Private::search },
+  //%% string mainPage
+  {  "mainPage",          &Private::mainPage },
+  //%% string classes
+  {  "classes",           &Private::classes },
+  //%% string classList
+  {  "classList",         &Private::classList },
+  //%% string classListDescription
+  {  "classListDescription", &Private::classListDescription },
+  //%% string classIndex
+  {  "classIndex",        &Private::classIndex },
+  //%% string concepts
+  {  "concepts",          &Private::concepts },
+  //%% string conceptDefintion
+  {  "conceptDefinition", &Private::conceptDefinition },
+  //%% string namespaceIndex
+  {  "namespaceIndex",    &Private::namespaceIndex },
+  //%% string classHierarchy
+  {  "classHierarchy",    &Private::classHierarchy },
+  //%% string classMembers
+  {  "classMembers",      &Private::classMembers },
+  //%% string classMembersDescription
+  {  "classMembersDescription",&Private::classMembersDescription },
+  //%% string modules
+  {  "modules",           &Private::modules },
+  //%% string moduleIndex
+  {  "moduleIndex",       &Private::moduleIndex },
+  //%% string namespaces
+  {  "namespaces",        &Private::namespaces },
+  //%% string fileIndex
+  {  "fileIndex",         &Private::fileIndex },
+  //%% string files
+  {  "files",             &Private::files },
+  //%% string pages
+  {  "pages",             &Private::pages },
+  //%% string examples
+  {  "examples",          &Private::examples },
+  //%% string namespaceList
+  {  "namespaceList",     &Private::namespaceList },
+  //%% string namespaceMembers
+  {  "namespaceMembers",  &Private::namespaceMembers },
+  //%% string fileList
+  {  "fileList",          &Private::fileList },
+  //%% string fileMembers
+  {  "fileMembers",       &Private::fileMembers },
+  //%% string fileMembersDescription
+  {  "fileMembersDescription", &Private::fileMembersDescription },
+  //%% string relatedPagesDescription
+  {  "relatedPagesDesc",  &Private::relatedPagesDesc },
+  //%% string more
+  {  "more",              &Private::more },
+  //%% string detailedDescription
+  {  "detailedDesc",      &Private::detailedDesc },
+  //%% string inheritanceDiagramFor
+  {  "inheritanceDiagramFor", &Private::inheritanceDiagramFor },
+  //%% string collaborationDiagramFor
+  {  "collaborationDiagramFor", &Private::collaborationDiagramFor },
+  //%% markerstring inheritsList
+  {  "inheritsList",      &Private::inheritsList },
+  //%% markerstring inheritedByList
+  {  "inheritedByList",   &Private::inheritedByList },
+  //%% markerstring definedAtLineInSourceFile
+  {  "definedAtLineInSourceFile", &Private::definedAtLineInSourceFile },
+  //%% string typeConstraints
+  {  "typeConstraints",   &Private::typeConstraints },
+  //%% string exampleList
+  {  "exampleList",       &Private::exampleList },
+  //%% string listOfAllMembers
+  {  "listOfAllMembers",  &Private::listOfAllMembers },
+  //%% string memberList
+  {  "memberList",        &Private::memberList },
+  //%% string theListOfAllMembers
+  {  "theListOfAllMembers",&Private::theListOfAllMembers },
+  //%% string incInheritedMembers
+  {  "incInheritedMembers",&Private::incInheritedMembers },
+  //%% string defineValue
+  {  "defineValue",        &Private::defineValue },
+  //%% string initialValue
+  {  "initialValue",       &Private::initialValue },
+  //%% markerstring implements
+  {  "implements",         &Private::implements },
+  //%% markerstring reimplements
+  {  "reimplements",       &Private::reimplements },
+  //%% markerstring implementedBy
+  {  "implementedBy",      &Private::implementedBy },
+  //%% markerstring reimplementedBy
+  {  "reimplementedBy",    &Private::reimplementedBy },
+  //%% markerstring sourceRefs
+  {  "sourceRefs",         &Private::sourceRefs },
+  //%% markerstring sourceRefBys
+  {  "sourceRefBys",       &Private::sourceRefBys },
+  //%% string callGraph
+  {  "callGraph",          &Private::callGraph },
+  //%% string callerGraph
+  {  "callerGraph",        &Private::callerGraph },
+  //%% string referencedByRelation
+  {  "referencedByRelation", &Private::referencedByRelation },
+  //%% string referencesRelation
+  {  "referencesRelation",   &Private::referencesRelation },
+  //%% markerstring inheritedFrom
+  {  "inheritedFrom",      &Private::inheritedFrom },
+  //%% string additionalInheritedMembers
+  {  "additionalInheritedMembers",&Private::additionalInheritedMembers },
+  //%% string includeDependencyGraph:container_name
+  {  "includeDependencyGraph",&Private::includeDependencyGraph },
+  //%% string includedByDependencyGraph
+  {  "includedByDependencyGraph",&Private::includedByDependencyGraph },
+  //%% string gotoSourceCode
+  {  "gotoSourceCode",     &Private::gotoSourceCode },
+  //%% string gotoDocumentation
+  {  "gotoDocumentation",  &Private::gotoDocumentation },
+  //%% string constantgroups
+  {  "constantgroups",     &Private::constantgroups },
+  //%% string classDocumentation
+  {  "classDocumentation", &Private::classDocumentation },
+  //%% string namespaceDocumentation
+  {  "namespaceDocumentation", &Private::namespaceDocumentation },
+  //%% string moduleDocumentation
+  {  "moduleDocumentation",&Private::moduleDocumentation },
+  //%% string fileDocumentation
+  {  "fileDocumentation",  &Private::fileDocumentation },
+  //%% string compoundMembers
+  {  "compoundMembers",    &Private::compoundMembers },
+  //%% string detailLevel
+  {  "detailLevel",        &Private::detailLevel },
+  //%% string fileListDescription
+  {  "fileListDescription",&Private::fileListDescription },
+  //%% string namespaceListDescription
+  {  "namespaceListDescription",&Private::namespaceListDescription },
+  //%% string conceptListDescription
+  {  "conceptListDescription",&Private::conceptListDescription },
+  //%% string directories
+  {  "directories",        &Private::directories },
+  //%% string moduleDescription
+  {  "modulesDescription", &Private::modulesDescription },
+  //%% string all
+  {  "all",                &Private::all },
+  //%% string functions
+  {  "functions",          &Private::functions },
+  //%% string variables
+  {  "variables",          &Private::variables },
+  //%% string typedefs
+  {  "typedefs",           &Private::typedefs },
+  //%% string enums
+  {  "enums",              &Private::enums },
+  //%% string enumValues
+  {  "enumValues",         &Private::enumerationValues },
+  //%% string properties
+  {  "properties",         &Private::properties },
+  //%% string events
+  {  "events",             &Private::events },
+  //%% string related
+  {  "related",            &Private::related },
+  //%% string macros
+  {  "macros",             &Private::macros },
+  //%% string namespaceMembersDescription
+  {  "namespaceMembersDescription",&Private::namespaceMembersDescription },
+  //%% string classHierarchyDescription
+  {  "classHierarchyDescription",&Private::classHierarchyDescription },
+  //%% string gotoGraphicalHierarchy
+  {  "gotoGraphicalHierarchy",&Private::gotoGraphicalHierarchy },
+  //%% string gotoTextualHierarchy
+  {  "gotoTextualHierarchy",&Private::gotoTextualHierarchy },
+  //%% string loading
+  {  "loading",            &Private::loading },
+  //%% string searching
+  {  "searching",          &Private::searching },
+  //%% string noMatches
+  {  "noMatches",          &Private::noMatches },
+  //%% string enumValue
+  {  "enumValue",          &Private::enumValue },
+  //%% string enumName
+  {  "enumName",           &Private::enumName },
+  //%% string referenceManual
+  {  "referenceManual",    &Private::referenceManual },
+  //%% string index
+  {  "index",              &Private::index },
+  //%% string panelSyncOn
+  {  "panelSyncOn",        &Private::panelSyncOn },
+  //%% string panelSyncOff
+  {  "panelSyncOff",       &Private::panelSyncOff },
+  //%% string dirDependencyGraph
+  {  "dirDependencyGraphFor", &Private::dirDependencyGraphFor },
+  //%% string providedByCategory
+  {  "providedByCategory", &Private::providedByCategory },
+  //%% string extendsClass
+  {  "extendsClass",       &Private::extendsClass },
+  //%% string examplesDescription
+  {  "examplesDescription",&Private::examplesDescription },
+  //%% string langstring
+  {  "langString",         &Private::langString },
+  //%% string code
+  {  "code",               &Private::code }
+} };
+//%% }
 
-TranslateContext::TranslateContext() : RefCountedContext("TranslateContext")
+TranslateContext::TranslateContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 TranslateContext::~TranslateContext()
 {
-  delete p;
 }
 
 TemplateVariant TranslateContext::get(const QCString &n) const
@@ -1301,6 +1236,8 @@ StringVector TranslateContext::fields() const
   return p->fields();
 }
 
+//------------------------------------------------------------------------------------------
+
 static TemplateVariant parseDoc(const Definition *def,const QCString &file,int line,
                                 const QCString &relPath,const QCString &docStr,bool isBrief)
 {
@@ -1426,8 +1363,6 @@ static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath)
 
 //------------------------------------------------------------------------
 
-//%% struct Symbol: shared info for all symbols
-//%% {
 template<typename T>
 class DefinitionContext
 {
@@ -1435,135 +1370,60 @@ class DefinitionContext
     DefinitionContext(const Definition *d) : m_def(d)
     {
       assert(d!=0);
-    }
-    virtual ~DefinitionContext() {}
-    void addBaseProperties(PropertyMapper<T> &inst)
-    {
-      //%% string name: the name of the symbol
-      inst.addProperty("name",&DefinitionContext::name);
-      //%% string bareName: the bare name of the symbol with scope info
-      inst.addProperty("bareName",&DefinitionContext::bareName);
-      //%% string relPath: the relative path to the root of the output (CREATE_SUBDIRS)
-      inst.addProperty("relPath",&DefinitionContext::relPath);
-      //%% string fileName: the file name of the output file associated with the symbol (without extension)
-      inst.addProperty("fileName",&DefinitionContext::fileName);
-      //%% string anchor: anchor within the page
-      inst.addProperty("anchor",&DefinitionContext::anchor);
-      //%% string details: the detailed documentation for this symbol
-      inst.addProperty("details",&DefinitionContext::details);
-      //%% string brief: the brief description for this symbol
-      inst.addProperty("brief",&DefinitionContext::brief);
-      //%% string inbodyDocs: the documentation found in the body
-      inst.addProperty("inbodyDocs",&DefinitionContext::inbodyDocs);
-      //%% string sourceFileName: the file name of the source file (without extension)
-      inst.addProperty("sourceFileName",&DefinitionContext::sourceFileName);
-      //%% bool isLinkable: can the symbol be linked to?
-      inst.addProperty("isLinkable",&DefinitionContext::isLinkable);
-      //%% bool isLinkableInProject: can the symbol be linked within this project?
-      inst.addProperty("isLinkableInProject",&DefinitionContext::isLinkableInProject);
-      //%% int dynSectionId: identifier that can be used for collapsible sections
-      inst.addProperty("dynSectionId",&DefinitionContext::dynSectionId);
-      //%% string language: the programming language in which the symbol is written
-      inst.addProperty("language",&DefinitionContext::language);
-      //%% string sourceDef: A link to the source definition
-      inst.addProperty("sourceDef",&DefinitionContext::sourceDef);
-      //%% list[Definition] navigationPath: Breadcrumb navigation path to this item
-      inst.addProperty("navigationPath",&DefinitionContext::navigationPath);
-      //%% string kind: Kind of compound object: class, namespace, module, package, page, dir
-      inst.addProperty("compoundKind",&DefinitionContext::compoundKind);
-      //%% bool isReference: is this definition imported via a tag file
-      inst.addProperty("isReference",&DefinitionContext::isReference);
-      //%% string externalReference: the link to the element in the remote documentation
-      inst.addProperty("externalReference",&DefinitionContext::externalReference);
-    }
-    TemplateVariant fileName() const
-    {
-      return m_def->getOutputFileBase();
-    }
-    TemplateVariant anchor() const
-    {
-      return m_def->anchor();
-    }
-    TemplateVariant sourceFileName() const
-    {
-      return m_def->getSourceFileBase();
-    }
-    TemplateVariant isLinkable() const
-    {
-      return m_def->isLinkable();
-    }
-    TemplateVariant isLinkableInProject() const
-    {
-      return m_def->isLinkableInProject();
-    }
-    TemplateVariant name() const
-    {
-      return m_def->displayName(TRUE);
-    }
-    TemplateVariant bareName() const
-    {
-      return m_def->displayName(FALSE);
-    }
-    QCString relPathAsString() const
-    {
-      static bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
-      return createSubdirs ? QCString("../../") : QCString("");
-    }
-    virtual TemplateVariant relPath() const
-    {
-      return relPathAsString();
-    }
-    TemplateVariant details() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.details || g_globals.outputFormat!=cache.detailsOutputFormat)
-      {
-        cache.details.reset(new TemplateVariant(parseDoc(m_def,m_def->docFile(),m_def->docLine(),
-                                            relPathAsString(),m_def->documentation(),FALSE)));
-        cache.detailsOutputFormat = g_globals.outputFormat;
-      }
-      return *cache.details;
-    }
-    TemplateVariant brief() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.brief || g_globals.outputFormat!=cache.briefOutputFormat)
+
+      if (m_def && !m_def->getSourceFileBase().isEmpty())
       {
-        if (m_def->hasBriefDescription())
+        TemplateStructIntfPtr lineLink = TemplateImmutableStruct::alloc(
         {
-          cache.brief.reset(new TemplateVariant(parseDoc(m_def,m_def->briefFile(),m_def->briefLine(),
-                             relPathAsString(),m_def->briefDescription(),TRUE)));
-          cache.briefOutputFormat = g_globals.outputFormat;
-        }
-        else
+          { "text",              TemplateVariant(m_def->getStartBodyLine())  },
+          { "isLinkable",        TemplateVariant(TRUE)                       },
+          { "fileName",          TemplateVariant(m_def->getSourceFileBase()) },
+          { "anchor",            TemplateVariant(m_def->getSourceAnchor())   },
+          { "isReference",       TemplateVariant(FALSE)                      },
+          { "externalReference", TemplateVariant("")                         }
+        });
+
+        QCString text = m_def->definitionType()==Definition::TypeFile ? m_def->name() :
+                                                  m_def->getBodyDef() ? m_def->getBodyDef()->name() :
+                                                                        m_def->displayName(TRUE);
+
+        TemplateStructIntfPtr fileLink = TemplateImmutableStruct::alloc(
         {
-          cache.brief.reset(new TemplateVariant(""));
-        }
+          { "text",              TemplateVariant(text)                       },
+          { "isLinkable",        TemplateVariant(TRUE)                       },
+          { "fileName",          TemplateVariant(m_def->getSourceFileBase()) },
+          { "anchor",            TemplateVariant("")                         },
+          { "isReference",       TemplateVariant(FALSE)                      },
+          { "externalReference", TemplateVariant("")                         }
+        });
+
+        m_sourceDef = TemplateImmutableList::alloc( { lineLink, fileLink });
       }
-      return *cache.brief;
-    }
-    TemplateVariant inbodyDocs() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.inbodyDocs || g_globals.outputFormat!=cache.inbodyDocsOutputFormat)
+      else
       {
-        if (!m_def->inbodyDocumentation().isEmpty())
-        {
-          cache.inbodyDocs.reset(new TemplateVariant(parseDoc(m_def,m_def->inbodyFile(),m_def->inbodyLine(),
-                                           relPathAsString(),m_def->inbodyDocumentation(),FALSE)));
-          cache.inbodyDocsOutputFormat = g_globals.outputFormat;
-        }
-        else
-        {
-          cache.inbodyDocs.reset(new TemplateVariant(""));
-        }
+        m_sourceDef = TemplateImmutableList::alloc( {} );
       }
-      return *cache.inbodyDocs;
-    }
-    TemplateVariant dynSectionId() const
-    {
-      return g_globals.dynSectionId;
     }
+    virtual ~DefinitionContext() {}
+
+  protected:
+    // Property getters
+    TemplateVariant fileName() const            { return m_def->getOutputFileBase(); }
+    TemplateVariant anchor() const              { return m_def->anchor(); }
+    TemplateVariant sourceFileName() const      { return m_def->getSourceFileBase(); }
+    TemplateVariant isLinkable() const          { return m_def->isLinkable(); }
+    TemplateVariant isLinkableInProject() const { return m_def->isLinkableInProject(); }
+    TemplateVariant name() const                { return m_def->displayName(TRUE); }
+    TemplateVariant bareName() const            { return m_def->displayName(FALSE); }
+    TemplateVariant details() const             { return m_cachable.details.get(this); }
+    TemplateVariant brief() const               { return m_cachable.brief.get(this); }
+    TemplateVariant inbodyDocs() const          { return m_cachable.inbodyDocs.get(this); }
+    TemplateVariant dynSectionId() const        { return g_globals.dynSectionId; }
+    TemplateVariant sourceDef() const           { return std::static_pointer_cast<TemplateListIntf>(m_sourceDef); }
+    TemplateVariant navigationPath() const      { return m_cachable.navPath.get(this); }
+    TemplateVariant partOfGroups() const        { return m_cachable.partOfGroups.get(this); }
+    TemplateVariant isReference() const         { return m_def->isReference(); }
+    TemplateVariant externalReference() const   { return m_def->externalReference(relPathAsString()); }
     TemplateVariant language() const
     {
       SrcLangExt lang = m_def->getLanguage();
@@ -1607,19 +1467,49 @@ class DefinitionContext
       }
       return result;
     }
-    TemplateVariant sourceDef() const
+
+  protected:
+
+    QCString relPathAsString() const
+    {
+      static bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
+      return createSubdirs ? QCString("../../") : QCString("");
+    }
+    virtual TemplateVariant relPath() const     { return relPathAsString(); }
+
+
+  private:
+
+    TemplateVariant createDetails() const
+    {
+      return TemplateVariant(parseDoc(m_def,m_def->docFile(),m_def->docLine(),
+                                      relPathAsString(),m_def->documentation(),FALSE));
+    }
+    TemplateVariant createBrief() const
+    {
+      if (m_def->hasBriefDescription())
+      {
+        return TemplateVariant(parseDoc(m_def,m_def->briefFile(),m_def->briefLine(),
+                               relPathAsString(),m_def->briefDescription(),TRUE));
+      }
+      else
+      {
+        return TemplateVariant("");
+      }
+    }
+    TemplateVariant createInbodyDocs() const
     {
-      Cachable &cache = getCache();
-      if (cache.sourceDef->count()==2)
+      if (!m_def->inbodyDocumentation().isEmpty())
       {
-        return cache.sourceDef.get();
+        return TemplateVariant(parseDoc(m_def,m_def->inbodyFile(),m_def->inbodyLine(),
+                                        relPathAsString(),m_def->inbodyDocumentation(),FALSE));
       }
       else
       {
-        return FALSE;
+        return TemplateVariant("");
       }
     }
-    void fillPath(const Definition *def,TemplateList *list) const
+    void fillPath(const Definition *def,TemplateVariantList &list) const
     {
       const Definition *outerScope = def->getOuterScope();
       Definition::DefType type = def->definitionType();
@@ -1631,102 +1521,77 @@ class DefinitionContext
       {
         fillPath((toFileDef(def))->getDirDef(),list);
       }
-      list->append(NavPathElemContext::alloc(def));
+      list.push_back(NavPathElemContext::alloc(def));
     }
-    TemplateVariant navigationPath() const
+    TemplateListIntfPtr createNavigationPath() const
     {
-      Cachable &cache = getCache();
-      if (!cache.navPath)
+      TemplateVariantList list;
+      if (m_def->getOuterScope() && m_def->getOuterScope()!=Doxygen::globalScope)
       {
-        TemplateList *list = TemplateList::alloc();
-        if (m_def->getOuterScope() && m_def->getOuterScope()!=Doxygen::globalScope)
-        {
-          fillPath(m_def,list);
-        }
-        else if (m_def->definitionType()==Definition::TypeFile && (toFileDef(m_def))->getDirDef())
-        {
-          fillPath((toFileDef(m_def))->getDirDef(),list);
-        }
-        cache.navPath.reset(list);
+        fillPath(m_def,list);
+      }
+      else if (m_def->definitionType()==Definition::TypeFile && (toFileDef(m_def))->getDirDef())
+      {
+        fillPath((toFileDef(m_def))->getDirDef(),list);
       }
-      return cache.navPath.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant isReference() const
+    TemplateListIntfPtr createPartOfGroups() const
     {
-      return m_def->isReference();
-    }
-    TemplateVariant externalReference() const
-    {
-      return m_def->externalReference(relPathAsString());
+      TemplateVariantList list;
+      list.reserve(m_def->partOfGroups().size());
+      for (const auto &gd : m_def->partOfGroups())
+      {
+        list.push_back(ModuleContext::alloc(gd));
+      }
+      return TemplateImmutableList::alloc(list);
     }
 
   protected:
     struct Cachable : public Definition::Cookie
     {
-      Cachable(const Definition *def) : detailsOutputFormat(ContextOutputFormat_Unspecified),
-                                  briefOutputFormat(ContextOutputFormat_Unspecified),
-                                  inbodyDocsOutputFormat(ContextOutputFormat_Unspecified)
-      {
-        sourceDef.reset(TemplateList::alloc());
-        lineLink.reset(TemplateStruct::alloc());
-        fileLink.reset(TemplateStruct::alloc());
-
-        if (def && !def->getSourceFileBase().isEmpty())
-        {
-          lineLink->set("text",def->getStartBodyLine());
-          lineLink->set("isLinkable",TRUE);
-          lineLink->set("fileName",def->getSourceFileBase());
-          lineLink->set("anchor",def->getSourceAnchor());
-          lineLink->set("isReference",FALSE);
-          lineLink->set("externalReference","");
-          if (def->definitionType()==Definition::TypeFile)
-          {
-            fileLink->set("text",def->name());
-          }
-          else if (def->getBodyDef())
-          {
-            fileLink->set("text",def->getBodyDef()->name());
-          }
-          else
-          {
-            fileLink->set("text",def->displayName(TRUE));
-          }
-          fileLink->set("isLinkable",TRUE);
-          fileLink->set("fileName",def->getSourceFileBase());
-          fileLink->set("anchor",QCString());
-          fileLink->set("isReference",FALSE);
-          fileLink->set("externalReference","");
-          sourceDef->append(lineLink.get());
-          sourceDef->append(fileLink.get());
-        }
-      }
-      std::unique_ptr<TemplateVariant> details;
-      ContextOutputFormat        detailsOutputFormat;
-      std::unique_ptr<TemplateVariant> brief;
-      ContextOutputFormat        briefOutputFormat;
-      std::unique_ptr<TemplateVariant> inbodyDocs;
-      ContextOutputFormat        inbodyDocsOutputFormat;
-      SharedPtr<TemplateList>    navPath;
-      SharedPtr<TemplateList>    sourceDef;
-      SharedPtr<TemplateStruct>  fileLink;
-      SharedPtr<TemplateStruct>  lineLink;
+      using DC = DefinitionContext<T>;
+      CachedItem<TemplateVariant,     DC, &DC::createDetails>        details;
+      CachedItem<TemplateVariant,     DC, &DC::createBrief>          brief;
+      CachedItem<TemplateVariant,     DC, &DC::createInbodyDocs>     inbodyDocs;
+      CachedItem<TemplateListIntfPtr, DC, &DC::createNavigationPath> navPath;
+      CachedItem<TemplateListIntfPtr, DC, &DC::createPartOfGroups>   partOfGroups;
     };
 
   private:
-    Cachable &getCache() const
-    {
-      Cachable *c = static_cast<Cachable*>(m_def->cookie());
-      assert(c!=0);
-      return *c;
-    }
+    Cachable m_cachable;
     const Definition *m_def;
+    TemplateListIntfPtr m_sourceDef;
+    static const PropertyMap< DefinitionContext<T> > s_baseProperties;
 };
+
+//%% struct Definition: shared info for all symbols
+//%% {
+#define BASE_PROPERTIES                                     \
+  {  "name",               &Private::name                }, \
+  {  "bareName",           &Private::bareName            }, \
+  {  "relPath",            &Private::relPath             }, \
+  {  "fileName",           &Private::fileName            }, \
+  {  "anchor",             &Private::anchor              }, \
+  {  "details",            &Private::details             }, \
+  {  "brief",              &Private::brief               }, \
+  {  "inbodyDocs",         &Private::inbodyDocs          }, \
+  {  "sourceFileName",     &Private::sourceFileName      }, \
+  {  "isLinkable",         &Private::isLinkable          }, \
+  {  "isLinkableInProject",&Private::isLinkableInProject }, \
+  {  "dynSectionId",       &Private::dynSectionId        }, \
+  {  "language",           &Private::language            }, \
+  {  "sourceDef",          &Private::sourceDef           }, \
+  {  "navigationPath",     &Private::navigationPath      }, \
+  {  "partOfGroups",       &Private::partOfGroups        }, \
+  {  "compoundKind",       &Private::compoundKind        }, \
+  {  "isReference",        &Private::isReference         }, \
+  {  "externalReference",  &Private::externalReference   }
 //%% }
 
+
 //------------------------------------------------------------------------
 
-//%% struct IncludeInfo: include file information
-//%% {
 class IncludeInfoContext::Private
 {
   public:
@@ -1734,15 +1599,6 @@ class IncludeInfoContext::Private
       m_info(info),
       m_lang(lang)
     {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("file",&Private::file);
-        s_inst.addProperty("name",&Private::name);
-        s_inst.addProperty("isImport",&Private::isImport);
-        s_inst.addProperty("isLocal",&Private::isLocal);
-        init=TRUE;
-      }
     }
     TemplateVariant get(const QCString &n) const
     {
@@ -1763,18 +1619,7 @@ class IncludeInfoContext::Private
     }
     TemplateVariant file() const
     {
-      if (!m_fileContext && m_info && m_info->fileDef)
-      {
-        m_fileContext.reset(FileContext::alloc(m_info->fileDef));
-      }
-      if (m_fileContext)
-      {
-        return m_fileContext.get();
-      }
-      else
-      {
-        return FALSE;
-      }
+      return m_fileContext.get(this);
     }
     TemplateVariant name() const
     {
@@ -1782,21 +1627,33 @@ class IncludeInfoContext::Private
     }
   private:
     const IncludeInfo *m_info;
-    mutable SharedPtr<FileContext> m_fileContext;
+    TemplateVariant createFileContext() const
+    {
+      return m_info && m_info->fileDef ?
+             TemplateVariant(FileContext::alloc(m_info->fileDef)) :
+             TemplateVariant(false);
+    }
+    CachedItem<TemplateVariant, Private, &Private::createFileContext> m_fileContext;
     SrcLangExt m_lang;
-    static PropertyMapper<IncludeInfoContext::Private> s_inst;
+    static const PropertyMap<IncludeInfoContext::Private> s_inst;
 };
 
-PropertyMapper<IncludeInfoContext::Private> IncludeInfoContext::Private::s_inst;
+//%% struct IncludeInfo: include file information
+//%% {
+const PropertyMap<IncludeInfoContext::Private> IncludeInfoContext::Private::s_inst {
+  {  "file",&Private::file },
+  {  "name",&Private::name },
+  {  "isImport",&Private::isImport },
+  {  "isLocal",&Private::isLocal }
+};
+//%% }
 
-IncludeInfoContext::IncludeInfoContext(const IncludeInfo *info,SrcLangExt lang) : RefCountedContext("IncludeContext")
+IncludeInfoContext::IncludeInfoContext(const IncludeInfo *info,SrcLangExt lang) : p(std::make_unique<Private>(info,lang))
 {
-  p = new Private(info,lang);
 }
 
 IncludeInfoContext::~IncludeInfoContext()
 {
-  delete p;
 }
 
 TemplateVariant IncludeInfoContext::get(const QCString &n) const
@@ -1826,14 +1683,12 @@ class IncludeInfoListContext::Private : public GenericNodeListContext
     }
 };
 
-IncludeInfoListContext::IncludeInfoListContext(const IncludeInfoList &list,SrcLangExt lang) : RefCountedContext("IncludeListContext")
+IncludeInfoListContext::IncludeInfoListContext(const IncludeInfoList &list,SrcLangExt lang) : p(std::make_unique<Private>(list,lang))
 {
-  p = new Private(list,lang);
 }
 
 IncludeInfoListContext::~IncludeInfoListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -1847,163 +1702,106 @@ TemplateVariant IncludeInfoListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *IncludeInfoListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr IncludeInfoListContext::createIterator() const
 {
   return p->createIterator();
 }
 
 //------------------------------------------------------------------------
 
-//%% struct Class(Symbol): class information
-//%% {
 class ClassContext::Private : public DefinitionContext<ClassContext::Private>
 {
   public:
     Private(const ClassDef *cd) : DefinitionContext<ClassContext::Private>(cd),
        m_classDef(cd)
     {
-      static bool init=FALSE;
-      if (!init)
-      {
-        addBaseProperties(s_inst);
-        s_inst.addProperty("title",                     &Private::title);
-        s_inst.addProperty("highlight",                 &Private::highlight);
-        s_inst.addProperty("subhighlight",              &Private::subHighlight);
-        s_inst.addProperty("hasDetails",                &Private::hasDetails);
-        s_inst.addProperty("generatedFromFiles",        &Private::generatedFromFiles);
-        s_inst.addProperty("usedFiles",                 &Private::usedFiles);
-        s_inst.addProperty("hasInheritanceDiagram",     &Private::hasInheritanceDiagram);
-        s_inst.addProperty("inheritanceDiagram",        &Private::inheritanceDiagram);
-        s_inst.addProperty("hasCollaborationDiagram",   &Private::hasCollaborationDiagram);
-        s_inst.addProperty("collaborationDiagram",      &Private::collaborationDiagram);
-        s_inst.addProperty("includeInfo",               &Private::includeInfo);
-        s_inst.addProperty("inherits",                  &Private::inherits);
-        s_inst.addProperty("inheritedBy",               &Private::inheritedBy);
-        s_inst.addProperty("unoIDLServices",            &Private::unoIDLServices);
-        s_inst.addProperty("unoIDLInterfaces",          &Private::unoIDLInterfaces);
-        s_inst.addProperty("signals",                   &Private::signals);
-        s_inst.addProperty("publicTypes",               &Private::publicTypes);
-        s_inst.addProperty("publicMethods",             &Private::publicMethods);
-        s_inst.addProperty("publicStaticMethods",       &Private::publicStaticMethods);
-        s_inst.addProperty("publicAttributes",          &Private::publicAttributes);
-        s_inst.addProperty("publicStaticAttributes",    &Private::publicStaticAttributes);
-        s_inst.addProperty("publicSlots",               &Private::publicSlots);
-        s_inst.addProperty("protectedTypes",            &Private::protectedTypes);
-        s_inst.addProperty("protectedMethods",          &Private::protectedMethods);
-        s_inst.addProperty("protectedStaticMethods",    &Private::protectedStaticMethods);
-        s_inst.addProperty("protectedAttributes",       &Private::protectedAttributes);
-        s_inst.addProperty("protectedStaticAttributes", &Private::protectedStaticAttributes);
-        s_inst.addProperty("protectedSlots",            &Private::protectedSlots);
-        s_inst.addProperty("privateTypes",              &Private::privateTypes);
-        s_inst.addProperty("privateMethods",            &Private::privateMethods);
-        s_inst.addProperty("privateStaticMethods",      &Private::privateStaticMethods);
-        s_inst.addProperty("privateAttributes",         &Private::privateAttributes);
-        s_inst.addProperty("privateStaticAttributes",   &Private::privateStaticAttributes);
-        s_inst.addProperty("privateSlots",              &Private::privateSlots);
-        s_inst.addProperty("packageTypes",              &Private::packageTypes);
-        s_inst.addProperty("packageMethods",            &Private::packageMethods);
-        s_inst.addProperty("packageStaticMethods",      &Private::packageStaticMethods);
-        s_inst.addProperty("packageAttributes",         &Private::packageAttributes);
-        s_inst.addProperty("packageStaticAttributes",   &Private::packageStaticAttributes);
-        s_inst.addProperty("properties",                &Private::properties);
-        s_inst.addProperty("events",                    &Private::events);
-        s_inst.addProperty("friends",                   &Private::friends);
-        s_inst.addProperty("related",                   &Private::related);
-        s_inst.addProperty("detailedTypedefs",          &Private::detailedTypedefs);
-        s_inst.addProperty("detailedEnums",             &Private::detailedEnums);
-        s_inst.addProperty("detailedServices",          &Private::detailedServices);
-        s_inst.addProperty("detailedInterfaces",        &Private::detailedInterfaces);
-        s_inst.addProperty("detailedConstructors",      &Private::detailedConstructors);
-        s_inst.addProperty("detailedMethods",           &Private::detailedMethods);
-        s_inst.addProperty("detailedRelated",           &Private::detailedRelated);
-        s_inst.addProperty("detailedVariables",         &Private::detailedVariables);
-        s_inst.addProperty("detailedProperties",        &Private::detailedProperties);
-        s_inst.addProperty("detailedEvents",            &Private::detailedEvents);
-        s_inst.addProperty("classes",                   &Private::classes);
-        s_inst.addProperty("innerClasses",              &Private::innerClasses);
-        s_inst.addProperty("compoundType",              &Private::compoundType);
-        s_inst.addProperty("templateDecls",             &Private::templateDecls);
-        s_inst.addProperty("typeConstraints",           &Private::typeConstraints);
-        s_inst.addProperty("examples",                  &Private::examples);
-        s_inst.addProperty("members",                   &Private::members);
-        s_inst.addProperty("allMembersList",            &Private::allMembersList);
-        s_inst.addProperty("allMembersFileName",        &Private::allMembersFileName);
-        s_inst.addProperty("memberGroups",              &Private::memberGroups);
-        s_inst.addProperty("additionalInheritedMembers",&Private::additionalInheritedMembers);
-        s_inst.addProperty("isSimple",                  &Private::isSimple);
-        s_inst.addProperty("categoryOf",                &Private::categoryOf);
-        init=TRUE;
-      }
-      if (!cd->cookie()) { cd->setCookie(new ClassContext::Private::Cachable(cd)); }
     }
     virtual ~Private() {}
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant title() const
-    {
-      return TemplateVariant(m_classDef->title());
-    }
-    TemplateVariant highlight() const
-    {
-      return TemplateVariant("classes");
-    }
-    TemplateVariant subHighlight() const
-    {
-      return TemplateVariant("");
-    }
-    TemplateVariant hasDetails() const
-    {
-      return m_classDef->hasDetailedDescription();
-    }
-    TemplateVariant generatedFromFiles() const
-    {
-      return m_classDef->generatedFromFiles();
-    }
-    TemplateVariant usedFiles() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.usedFiles)
-      {
-        cache.usedFiles.reset(UsedFilesContext::alloc(m_classDef));
-      }
-      return cache.usedFiles.get();
-    }
-    DotClassGraph *getClassGraph() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.classGraph)
-      {
-        cache.classGraph.reset(new DotClassGraph(m_classDef,Inheritance));
-      }
-      return cache.classGraph.get();
-    }
-    int numInheritanceNodes() const
-    {
-      Cachable &cache = getCache();
-      if (cache.inheritanceNodes==-1)
-      {
-        cache.inheritanceNodes=m_classDef->countInheritanceNodes();
-      }
-      return cache.inheritanceNodes>0;
-    }
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const       { return s_inst.get(this,n); }
+    StringVector fields() const                        { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant title() const                      { return TemplateVariant(m_classDef->title()); }
+    TemplateVariant highlight() const                  { return TemplateVariant("classes"); }
+    TemplateVariant subHighlight() const               { return TemplateVariant(""); }
+    TemplateVariant hasDetails() const                 { return m_classDef->hasDetailedDescription(); }
+    TemplateVariant generatedFromFiles() const         { return m_classDef->generatedFromFiles(); }
+    TemplateVariant usedFiles() const                  { return m_cachable.usedFiles.get(this); }
+    DotClassGraphPtr getClassGraph() const             { return m_cachable.classGraph.get(this); }
+    int numInheritanceNodes() const                    { return m_cachable.numInheritanceNodes.get(this); }
+    TemplateVariant includeInfo() const                { return m_cachable.includeInfo.get(this); }
+    TemplateVariant inherits() const                   { return m_cachable.inheritsList.get(this); }
+    TemplateVariant inheritedBy() const                { return m_cachable.inheritedByList.get(this); }
+    TemplateVariant unoIDLServices() const             { return m_cachable.unoIDLServices.get(this); }
+    TemplateVariant unoIDLInterfaces() const           { return m_cachable.unoIDLInterfaces.get(this); }
+    TemplateVariant signals() const                    { return m_cachable.signals.get(this); }
+    TemplateVariant publicTypes() const                { return m_cachable.publicTypes.get(this); }
+    TemplateVariant publicMethods() const              { return m_cachable.publicMethods.get(this); }
+    TemplateVariant publicStaticMethods() const        { return m_cachable.publicStaticMethods.get(this); }
+    TemplateVariant publicAttributes() const           { return m_cachable.publicAttributes.get(this); }
+    TemplateVariant publicStaticAttributes() const     { return m_cachable.publicStaticAttributes.get(this); }
+    TemplateVariant publicSlots() const                { return m_cachable.publicSlots.get(this); }
+    TemplateVariant protectedTypes() const             { return m_cachable.protectedTypes.get(this); }
+    TemplateVariant protectedMethods() const           { return m_cachable.protectedMethods.get(this); }
+    TemplateVariant protectedStaticMethods() const     { return m_cachable.protectedStaticMethods.get(this); }
+    TemplateVariant protectedAttributes() const        { return m_cachable.protectedAttributes.get(this); }
+    TemplateVariant protectedStaticAttributes() const  { return m_cachable.protectedStaticAttributes.get(this); }
+    TemplateVariant protectedSlots() const             { return m_cachable.protectedSlots.get(this); }
+    TemplateVariant privateTypes() const               { return m_cachable.privateTypes.get(this); }
+    TemplateVariant privateSlots() const               { return m_cachable.privateSlots.get(this); }
+    TemplateVariant privateMethods() const             { return m_cachable.privateMethods.get(this); }
+    TemplateVariant privateStaticMethods() const       { return m_cachable.privateStaticMethods.get(this); }
+    TemplateVariant privateAttributes() const          { return m_cachable.privateAttributes.get(this); }
+    TemplateVariant privateStaticAttributes() const    { return m_cachable.privateStaticAttributes.get(this); }
+    TemplateVariant packageTypes() const               { return m_cachable.packageTypes.get(this); }
+    TemplateVariant packageMethods() const             { return m_cachable.packageMethods.get(this); }
+    TemplateVariant packageStaticMethods() const       { return m_cachable.packageStaticMethods.get(this); }
+    TemplateVariant packageAttributes() const          { return m_cachable.packageAttributes.get(this); }
+    TemplateVariant packageStaticAttributes() const    { return m_cachable.packageStaticAttributes.get(this); }
+    TemplateVariant properties() const                 { return m_cachable.properties.get(this); }
+    TemplateVariant events() const                     { return m_cachable.events.get(this); }
+    TemplateVariant friends() const                    { return m_cachable.friends.get(this); }
+    TemplateVariant related() const                    { return m_cachable.related.get(this); }
+    TemplateVariant detailedTypedefs() const           { return m_cachable.detailedTypedefs.get(this); }
+    TemplateVariant detailedEnums() const              { return m_cachable.detailedEnums.get(this); }
+    TemplateVariant detailedServices() const           { return m_cachable.detailedServices.get(this); }
+    TemplateVariant detailedInterfaces() const         { return m_cachable.detailedInterfaces.get(this); }
+    TemplateVariant detailedConstructors() const       { return m_cachable.detailedConstructors.get(this); }
+    TemplateVariant detailedMethods() const            { return m_cachable.detailedMethods.get(this); }
+    TemplateVariant detailedRelated() const            { return m_cachable.detailedRelated.get(this); }
+    TemplateVariant detailedVariables() const          { return m_cachable.detailedVariables.get(this); }
+    TemplateVariant detailedProperties() const         { return m_cachable.detailedProperties.get(this); }
+    TemplateVariant detailedEvents() const             { return m_cachable.detailedEvents.get(this); }
+    TemplateVariant classes() const                    { return m_cachable.classes.get(this); }
+    TemplateVariant innerClasses() const               { return m_cachable.innerClasses.get(this); }
+    TemplateVariant compoundType() const               { return m_classDef->compoundTypeString(); }
+    TemplateVariant templateDecls() const              { return m_cachable.templateDecls.get(this); }
+    TemplateVariant typeConstraints() const            { return m_cachable.typeConstraints.get(this); }
+    TemplateVariant examples() const                   { return m_cachable.examples.get(this); }
+    TemplateVariant members() const                    { return m_cachable.members.get(this); }
+    TemplateVariant allMembersList() const             { return m_cachable.allMembersList.get(this); }
+    TemplateVariant allMembersFileName() const         { return m_classDef->getMemberListFileName(); }
+    TemplateVariant memberGroups() const               { return m_cachable.memberGroups.get(this); }
+    TemplateVariant additionalInheritedMembers() const { return m_cachable.additionalInheritedMembers.get(this); }
+    TemplateVariant isSimple() const                   { return m_classDef->isSimple(); }
+    TemplateVariant categoryOf() const                 { return m_cachable.categoryOf.get(this); }
+
     TemplateVariant hasInheritanceDiagram() const
     {
       bool result=FALSE;
-      static bool haveDot       = Config_getBool(HAVE_DOT);
-      static bool classDiagrams = Config_getBool(CLASS_DIAGRAMS);
-      static bool classGraph    = Config_getBool(CLASS_GRAPH);
-      if (haveDot && (classDiagrams || classGraph))
+      static bool haveDot    = Config_getBool(HAVE_DOT);
+      static auto classGraph = Config_getEnum(CLASS_GRAPH);
+      bool classGraphEnabled = classGraph==CLASS_GRAPH_t::YES || classGraph==CLASS_GRAPH_t::GRAPH;
+
+      if (haveDot && classGraphEnabled)
       {
-        DotClassGraph *cg = getClassGraph();
+        DotClassGraphPtr cg = getClassGraph();
         result = !cg->isTrivial() && !cg->isTooBig();
       }
-      else if (classDiagrams)
+      else if (classGraphEnabled)
       {
         result = numInheritanceNodes()>0;
       }
@@ -2012,19 +1810,20 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
     TemplateVariant inheritanceDiagram() const
     {
       TextStream t;
-      static bool haveDot       = Config_getBool(HAVE_DOT);
-      static bool classDiagrams = Config_getBool(CLASS_DIAGRAMS);
-      static bool classGraph    = Config_getBool(CLASS_GRAPH);
-      if (haveDot && (classDiagrams || classGraph))
+      static bool haveDot    = Config_getBool(HAVE_DOT);
+      static auto classGraph = Config_getEnum(CLASS_GRAPH);
+      bool classGraphEnabled = classGraph==CLASS_GRAPH_t::YES || classGraph==CLASS_GRAPH_t::GRAPH;
+
+      if (haveDot && classGraphEnabled)
       {
-        DotClassGraph *cg = getClassGraph();
+        DotClassGraphPtr cg = getClassGraph();
         switch (g_globals.outputFormat)
         {
           case ContextOutputFormat_Html:
             {
               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
                              g_globals.outputDir,
-                             g_globals.outputDir+Portable::pathSeparator()+m_classDef->getOutputFileBase()+Doxygen::htmlFileExtension,
+                             g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_classDef->getOutputFileBase()),
                              relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
                             );
             }
@@ -2045,7 +1844,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
         }
         g_globals.dynSectionId++;
       }
-      else if (classDiagrams)
+      else if (classGraphEnabled)
       {
         ClassDiagram d(m_classDef);
         switch (g_globals.outputFormat)
@@ -2093,14 +1892,9 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
       }
       return TemplateVariant(t.str().c_str(),TRUE);
     }
-    DotClassGraph *getCollaborationGraph() const
+    DotClassGraphPtr getCollaborationGraph() const
     {
-      Cachable &cache = getCache();
-      if (!cache.collaborationGraph)
-      {
-        cache.collaborationGraph.reset(new DotClassGraph(m_classDef,Collaboration));
-      }
-      return cache.collaborationGraph.get();
+      return m_cachable.collaborationGraph.get(this);
     }
     TemplateVariant hasCollaborationDiagram() const
     {
@@ -2113,14 +1907,14 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
       TextStream t;
       if (haveDot)
       {
-        DotClassGraph *cg = getCollaborationGraph();
+        DotClassGraphPtr cg = getCollaborationGraph();
         switch (g_globals.outputFormat)
         {
           case ContextOutputFormat_Html:
             {
               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
                              g_globals.outputDir,
-                             g_globals.outputDir+Portable::pathSeparator()+m_classDef->getOutputFileBase()+Doxygen::htmlFileExtension,
+                             g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_classDef->getOutputFileBase()),
                              relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
                             );
             }
@@ -2144,267 +1938,270 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
       return TemplateVariant(t.str().c_str(),TRUE);
     }
 
-    TemplateVariant includeInfo() const
+
+  private:
+
+    TemplateVariant createIncludeInfo() const
     {
-      Cachable &cache = getCache();
-      if (!cache.includeInfo && m_classDef->includeInfo())
-      {
-        cache.includeInfo.reset(IncludeInfoContext::alloc(m_classDef->includeInfo(),m_classDef->getLanguage()));
-      }
-      if (cache.includeInfo)
-      {
-        return cache.includeInfo.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
+      return m_classDef->includeInfo() ?
+             IncludeInfoContext::alloc(m_classDef->includeInfo(),m_classDef->getLanguage()) :
+             TemplateVariant(false);
     }
-    TemplateVariant inherits() const
+    TemplateVariant createInheritsList() const
     {
-      Cachable &cache = getCache();
-      if (!cache.inheritsList)
-      {
-        cache.inheritsList.reset(InheritanceListContext::alloc(m_classDef->baseClasses(),TRUE));
-      }
-      return cache.inheritsList.get();
+      return InheritanceListContext::alloc(m_classDef->baseClasses(),TRUE);
     }
-    TemplateVariant inheritedBy() const
+    TemplateVariant createInheritedByList() const
     {
-      Cachable &cache = getCache();
-      if (!cache.inheritedByList)
-      {
-        cache.inheritedByList.reset(InheritanceListContext::alloc(m_classDef->subClasses(),FALSE));
-      }
-      return cache.inheritedByList.get();
+      return InheritanceListContext::alloc(m_classDef->subClasses(),FALSE);
+    }
+    DotClassGraphPtr createClassGraph() const
+    {
+      return std::make_shared<DotClassGraph>(m_classDef,Inheritance);
+    }
+    DotClassGraphPtr createCollaborationGraph() const
+    {
+      return std::make_shared<DotClassGraph>(m_classDef,Collaboration);
     }
-    TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list,
-                                  MemberListType type,const QCString &title,bool=FALSE) const
+    TemplateVariant createClasses() const
     {
-      if (!list)
+      TemplateVariantList classList;
+      classList.reserve(m_classDef->getClasses().size());
+      for (const auto &cd : m_classDef->getClasses())
       {
-        const MemberList *ml = m_classDef->getMemberList(type);
-        if (ml)
+        if (cd->visibleInParentsDeclList())
         {
-          list.reset(MemberListInfoContext::alloc(m_classDef,relPathAsString(),ml,title,""));
+          classList.push_back(ClassContext::alloc(cd));
         }
       }
-      if (list)
-      {
-        return list.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
-    }
-    TemplateVariant unoIDLServices() const
-    {
-      return getMemberList(getCache().unoIDLServices,MemberListType_services,theTranslator->trServices());
+      return TemplateImmutableList::alloc(classList);
     }
-    TemplateVariant unoIDLInterfaces() const
+    TemplateVariant createInnerClasses() const
     {
-      return getMemberList(getCache().unoIDLInterfaces,MemberListType_interfaces,theTranslator->trInterfaces());
+      TemplateVariantList classList;
+      classList.reserve(m_classDef->getClasses().size());
+      for (const auto &cd : m_classDef->getClasses())
+      {
+        if (!cd->isAnonymous() &&
+            cd->isLinkableInProject() &&
+            cd->isEmbeddedInOuterScope() &&
+            cd->partOfGroups().empty()
+           )
+        {
+          classList.push_back(ClassContext::alloc(cd));
+        }
+      }
+      return TemplateImmutableList::alloc(classList);
     }
-    TemplateVariant signals() const
+    TemplateVariant createMemberList(MemberListType type,const QCString &title) const
     {
-      return getMemberList(getCache().signals,MemberListType_signals,theTranslator->trSignals());
+      const MemberList *ml = m_classDef->getMemberList(type);
+      return ml ? TemplateVariant(MemberListInfoContext::alloc(m_classDef,relPathAsString(),ml,title,""))
+                : TemplateVariant(false);
     }
-    TemplateVariant publicTypes() const
+    TemplateVariant createPublicTypes() const
     {
-      return getMemberList(getCache().publicTypes,MemberListType_pubTypes,theTranslator->trPublicTypes());
+      return createMemberList(MemberListType_pubTypes,theTranslator->trPublicTypes());
     }
-    TemplateVariant publicMethods() const
+    TemplateVariant createPublicMethods() const
     {
-      return getMemberList(getCache().publicMethods,MemberListType_pubMethods,
+      return createMemberList(MemberListType_pubMethods,
           m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trInstanceMethods()
                                                      : theTranslator->trPublicMembers());
     }
-    TemplateVariant publicStaticMethods() const
+    TemplateVariant createPublicStaticMethods() const
     {
-      return getMemberList(getCache().publicStaticMethods,MemberListType_pubStaticMethods,
+      return createMemberList(MemberListType_pubStaticMethods,
           m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trClassMethods()
                                                      : theTranslator->trStaticPublicMembers());
     }
-    TemplateVariant publicAttributes() const
+    TemplateVariant createPublicAttributes() const
     {
-      return getMemberList(getCache().publicAttributes,MemberListType_pubAttribs,theTranslator->trPublicAttribs());
+      return createMemberList(MemberListType_pubAttribs,theTranslator->trPublicAttribs());
     }
-    TemplateVariant publicStaticAttributes() const
+    TemplateVariant createPublicStaticAttributes() const
     {
-      return getMemberList(getCache().publicStaticAttributes,MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs());
+      return createMemberList(MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs());
     }
-    TemplateVariant publicSlots() const
+    TemplateVariant createPublicSlots() const
     {
-      return getMemberList(getCache().publicSlots,MemberListType_pubSlots,theTranslator->trPublicSlots());
+      return createMemberList(MemberListType_pubSlots,theTranslator->trPublicSlots());
     }
-    TemplateVariant protectedTypes() const
+    TemplateVariant createUnoIDLServices() const
     {
-      return getMemberList(getCache().protectedTypes,MemberListType_proTypes,theTranslator->trProtectedTypes());
+      return createMemberList(MemberListType_services,theTranslator->trServices());
     }
-    TemplateVariant protectedMethods() const
+    TemplateVariant createUnoIDLInterfaces() const
     {
-      return getMemberList(getCache().protectedMethods,MemberListType_proMethods,theTranslator->trProtectedMembers());
+      return createMemberList(MemberListType_interfaces,theTranslator->trInterfaces());
     }
-    TemplateVariant protectedStaticMethods() const
+    TemplateVariant createSignals() const
     {
-      return getMemberList(getCache().protectedStaticMethods,MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers());
+      return createMemberList(MemberListType_signals,theTranslator->trSignals());
     }
-    TemplateVariant protectedAttributes() const
+    TemplateVariant createProtectedTypes() const
     {
-      return getMemberList(getCache().protectedAttributes,MemberListType_proAttribs,theTranslator->trProtectedAttribs());
+      return createMemberList(MemberListType_proTypes,theTranslator->trProtectedTypes());
     }
-    TemplateVariant protectedStaticAttributes() const
+    TemplateVariant createProtectedMethods() const
     {
-      return getMemberList(getCache().protectedStaticAttributes,MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs());
+      return createMemberList(MemberListType_proMethods,theTranslator->trProtectedMembers());
     }
-    TemplateVariant protectedSlots() const
+    TemplateVariant createProtectedStaticMethods() const
     {
-      return getMemberList(getCache().protectedSlots,MemberListType_proSlots,theTranslator->trProtectedSlots());
+      return createMemberList(MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers());
     }
-    TemplateVariant privateTypes() const
+    TemplateVariant createProtectedAttributes() const
     {
-      return getMemberList(getCache().privateTypes,MemberListType_priTypes,theTranslator->trPrivateTypes());
+      return createMemberList(MemberListType_proAttribs,theTranslator->trProtectedAttribs());
     }
-    TemplateVariant privateSlots() const
+    TemplateVariant createProtectedStaticAttributes() const
     {
-      return getMemberList(getCache().privateSlots,MemberListType_priSlots,theTranslator->trPrivateSlots());
+      return createMemberList(MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs());
     }
-    TemplateVariant privateMethods() const
+    TemplateVariant createProtectedSlots() const
     {
-      return getMemberList(getCache().privateMethods,MemberListType_priMethods,theTranslator->trPrivateMembers());
+      return createMemberList(MemberListType_proSlots,theTranslator->trProtectedSlots());
     }
-    TemplateVariant privateStaticMethods() const
+    TemplateVariant createPrivateTypes() const
     {
-      return getMemberList(getCache().privateStaticMethods,MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers());
+      return createMemberList(MemberListType_priTypes,theTranslator->trPrivateTypes());
     }
-    TemplateVariant privateAttributes() const
+    TemplateVariant createPrivateSlots() const
     {
-      return getMemberList(getCache().privateAttributes,MemberListType_priAttribs,theTranslator->trPrivateAttribs());
+      return createMemberList(MemberListType_priSlots,theTranslator->trPrivateSlots());
     }
-    TemplateVariant privateStaticAttributes() const
+    TemplateVariant createPrivateMethods() const
     {
-      return getMemberList(getCache().privateStaticAttributes,MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs());
+      return createMemberList(MemberListType_priMethods,theTranslator->trPrivateMembers());
     }
-    TemplateVariant packageTypes() const
+    TemplateVariant createPrivateStaticMethods() const
     {
-      return getMemberList(getCache().packageTypes,MemberListType_pacTypes,theTranslator->trPackageTypes());
+      return createMemberList(MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers());
     }
-    TemplateVariant packageMethods() const
+    TemplateVariant createPrivateAttributes() const
     {
-      return getMemberList(getCache().packageMethods,MemberListType_pacMethods,theTranslator->trPackageMembers());
+      return createMemberList(MemberListType_priAttribs,theTranslator->trPrivateAttribs());
     }
-    TemplateVariant packageStaticMethods() const
+    TemplateVariant createPrivateStaticAttributes() const
     {
-      return getMemberList(getCache().packageStaticMethods,MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers());
+      return createMemberList(MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs());
     }
-    TemplateVariant packageAttributes() const
+    TemplateVariant createPackageTypes() const
     {
-      return getMemberList(getCache().packageAttributes,MemberListType_pacAttribs,theTranslator->trPackageAttribs());
+      return createMemberList(MemberListType_pacTypes,theTranslator->trPackageTypes());
     }
-    TemplateVariant packageStaticAttributes() const
+    TemplateVariant createPackageMethods() const
     {
-      return getMemberList(getCache().packageStaticAttributes,MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs());
+      return createMemberList(MemberListType_pacMethods,theTranslator->trPackageMembers());
     }
-    TemplateVariant properties() const
+    TemplateVariant createPackageStaticMethods() const
     {
-      return getMemberList(getCache().properties,MemberListType_properties,theTranslator->trProperties());
+      return createMemberList(MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers());
     }
-    TemplateVariant events() const
+    TemplateVariant createPackageAttributes() const
     {
-      return getMemberList(getCache().events,MemberListType_events,theTranslator->trEvents());
+      return createMemberList(MemberListType_pacAttribs,theTranslator->trPackageAttribs());
     }
-    TemplateVariant friends() const
+    TemplateVariant createPackageStaticAttributes() const
     {
-      return getMemberList(getCache().friends,MemberListType_friends,theTranslator->trFriends());
+      return createMemberList(MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs());
     }
-    TemplateVariant related() const
+    TemplateVariant createProperties() const
     {
-      return getMemberList(getCache().related,MemberListType_related,theTranslator->trRelatedFunctions());
+      return createMemberList(MemberListType_properties,theTranslator->trProperties());
     }
-    TemplateVariant detailedTypedefs() const
+    TemplateVariant createEvents() const
     {
-      return getMemberList(getCache().detailedTypedefs,MemberListType_typedefMembers,theTranslator->trMemberTypedefDocumentation(),TRUE);
+      return createMemberList(MemberListType_events,theTranslator->trEvents());
     }
-    TemplateVariant detailedEnums() const
+    TemplateVariant createFriends() const
     {
-      return getMemberList(getCache().detailedEnums,MemberListType_enumMembers,theTranslator->trMemberEnumerationDocumentation(),TRUE);
+      return createMemberList(MemberListType_friends,theTranslator->trFriends());
     }
-    TemplateVariant detailedServices() const
+    TemplateVariant createRelated() const
     {
-      return getMemberList(getCache().detailedServices,MemberListType_serviceMembers,theTranslator->trServices(),TRUE);
+      return createMemberList(MemberListType_related,theTranslator->trRelatedFunctions());
     }
-    TemplateVariant detailedInterfaces() const
+    TemplateVariant createDetailedTypedefs() const
     {
-      return getMemberList(getCache().detailedInterfaces,MemberListType_interfaceMembers,theTranslator->trInterfaces(),TRUE);
+      return createMemberList(MemberListType_typedefMembers,theTranslator->trMemberTypedefDocumentation());
     }
-    TemplateVariant detailedConstructors() const
+    TemplateVariant createDetailedEnums() const
     {
-      return getMemberList(getCache().detailedConstructors,MemberListType_constructors,theTranslator->trConstructorDocumentation(),TRUE);
+      return createMemberList(MemberListType_enumMembers,theTranslator->trMemberEnumerationDocumentation());
     }
-    TemplateVariant detailedMethods() const
+    TemplateVariant createDetailedServices() const
     {
-      return getMemberList(getCache().detailedMethods,MemberListType_functionMembers,theTranslator->trMemberFunctionDocumentation(),TRUE);
+      return createMemberList(MemberListType_serviceMembers,theTranslator->trServices());
     }
-    TemplateVariant detailedRelated() const
+    TemplateVariant createDetailedInterfaces() const
     {
-      return getMemberList(getCache().detailedRelated,MemberListType_relatedMembers,theTranslator->trRelatedFunctionDocumentation(),TRUE);
+      return createMemberList(MemberListType_interfaceMembers,theTranslator->trInterfaces());
     }
-    TemplateVariant detailedVariables() const
+    TemplateVariant createDetailedConstructors() const
     {
-      return getMemberList(getCache().detailedVariables,MemberListType_variableMembers,theTranslator->trMemberDataDocumentation(),TRUE);
+      return createMemberList(MemberListType_constructors,theTranslator->trConstructorDocumentation());
     }
-    TemplateVariant detailedProperties() const
+    TemplateVariant createDetailedMethods() const
     {
-      return getMemberList(getCache().detailedProperties,MemberListType_propertyMembers,theTranslator->trPropertyDocumentation(),TRUE);
+      return createMemberList(MemberListType_functionMembers,theTranslator->trMemberFunctionDocumentation());
     }
-    TemplateVariant detailedEvents() const
+    TemplateVariant createDetailedRelated() const
     {
-      return getMemberList(getCache().detailedEvents,MemberListType_eventMembers,theTranslator->trEventDocumentation(),TRUE);
+      return createMemberList(MemberListType_relatedMembers,theTranslator->trRelatedFunctionDocumentation());
     }
-    TemplateVariant classes() const
+    TemplateVariant createDetailedVariables() const
     {
-      Cachable &cache = getCache();
-      if (!cache.classes)
-      {
-        TemplateList *classList = TemplateList::alloc();
-        for (const auto &cd : m_classDef->getClasses())
-        {
-          if (cd->visibleInParentsDeclList())
-          {
-            classList->append(ClassContext::alloc(cd));
-          }
-        }
-        cache.classes.reset(classList);
-      }
-      return cache.classes.get();
+      return createMemberList(MemberListType_variableMembers,theTranslator->trMemberDataDocumentation());
+    }
+    TemplateVariant createDetailedProperties() const
+    {
+      return createMemberList(MemberListType_propertyMembers,theTranslator->trPropertyDocumentation());
+    }
+    TemplateVariant createDetailedEvents() const
+    {
+      return createMemberList(MemberListType_eventMembers,theTranslator->trEventDocumentation());
+    }
+    TemplateVariant createMemberGroups() const
+    {
+      return !m_classDef->getMemberGroups().empty() ?
+        MemberGroupListContext::alloc(m_classDef,relPathAsString(),m_classDef->getMemberGroups(),m_classDef->subGrouping()) :
+        MemberGroupListContext::alloc();
+    }
+    TemplateVariant createAllMembersList() const
+    {
+       return AllMembersListContext::alloc(m_classDef->memberNameInfoLinkedMap());
+    }
+    TemplateVariant createTypeConstraints() const
+    {
+      return !m_classDef->typeConstraints().empty() ?
+          TemplateVariant(ArgumentListContext::alloc(m_classDef->typeConstraints(),m_classDef,relPathAsString())) :
+          TemplateVariant(false);
     }
-    TemplateVariant innerClasses() const
+    TemplateVariant createExamples() const
     {
-      Cachable &cache = getCache();
-      if (!cache.innerClasses)
+      TemplateVariantList list;
+      list.reserve(m_classDef->getExamples().size());
+      if (m_classDef->hasExamples())
       {
-        TemplateList *classList = TemplateList::alloc();
-        for (const auto &cd : m_classDef->getClasses())
+        for (const auto &ex : m_classDef->getExamples())
         {
-          if (!cd->isAnonymous() &&
-              cd->isLinkableInProject() &&
-              cd->isEmbeddedInOuterScope() &&
-              cd->partOfGroups().empty()
-             )
+          TemplateStructIntfPtr s = TemplateImmutableStruct::alloc(
           {
-            classList->append(ClassContext::alloc(cd));
-          }
+            { "text",              TemplateVariant(ex.name)   },
+            { "isLinkable",        TemplateVariant(TRUE)      },
+            { "anchor",            TemplateVariant(ex.anchor) },
+            { "fileName",          TemplateVariant(ex.file)   },
+            { "isReference",       TemplateVariant(FALSE)     },
+            { "externalReference", TemplateVariant("")        }
+          });
+          list.push_back(s);
         }
-        cache.innerClasses.reset(classList);
       }
-      return cache.innerClasses.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant compoundType() const
-    {
-      return m_classDef->compoundTypeString();
-    }
-    void addTemplateDecls(const Definition *d,TemplateList *tl) const
+    void addTemplateDecls(const Definition *d,TemplateVariantList &tl) const
     {
       if (d->definitionType()==Definition::TypeClass)
       {
@@ -2416,300 +2213,267 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
         const ClassDef *cd=toClassDef(d);
         if (!cd->templateArguments().empty())
         {
-          ArgumentListContext *al = ArgumentListContext::alloc(cd->templateArguments(),cd,relPathAsString());
+          TemplateListIntfPtr al = ArgumentListContext::alloc(cd->templateArguments(),cd,relPathAsString());
           // since a TemplateVariant does take ownership of the object, we add it
           // a separate list just to be able to delete it and avoid a memory leak
-          tl->append(al);
-        }
-      }
-    }
-    void addExamples(TemplateList *list) const
-    {
-      if (m_classDef->hasExamples())
-      {
-        for (const auto &ex : m_classDef->getExamples())
-        {
-          TemplateStruct *s = TemplateStruct::alloc();
-          s->set("text",ex.name);
-          s->set("isLinkable",TRUE);
-          s->set("anchor",ex.anchor);
-          s->set("fileName",ex.file);
-          s->set("isReference",FALSE);
-          s->set("externalReference","");
-          list->append(s);
-        }
-      }
-    }
-    TemplateVariant templateDecls() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.templateDecls)
-      {
-        TemplateList *tl = TemplateList::alloc();
-        addTemplateDecls(m_classDef,tl);
-        cache.templateDecls.reset(tl);
-      }
-      return cache.templateDecls.get();
-    }
-    TemplateVariant typeConstraints() const
-    {
-      if (!m_classDef->typeConstraints().empty())
-      {
-        Cachable &cache = getCache();
-        if (!cache.typeConstraints && !m_classDef->typeConstraints().empty())
-        {
-          cache.typeConstraints.reset(ArgumentListContext::alloc(m_classDef->typeConstraints(),m_classDef,relPathAsString()));
-        }
-        return cache.typeConstraints.get();
-      }
-      return FALSE;
-    }
-    TemplateVariant examples() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.examples)
-      {
-        TemplateList *exampleList = TemplateList::alloc();
-        addExamples(exampleList);
-        cache.examples.reset(exampleList);
-      }
-      return cache.examples.get();
-    }
-    void addMembers(const ClassDef *cd,MemberListType lt) const
+          tl.push_back(al);
+        }
+      }
+    }
+    TemplateVariant createTemplateDecls() const
+    {
+      TemplateVariantList tl;
+      addTemplateDecls(m_classDef,tl);
+      return TemplateImmutableList::alloc(tl);
+    }
+    TemplateVariant createAdditionalInheritedMembers() const
+    {
+      TemplateListIntfPtr list = InheritedMemberInfoListContext::alloc();
+      auto ctx = std::dynamic_pointer_cast<InheritedMemberInfoListContext>(list);
+      ctx->addMemberList(m_classDef,MemberListType_pubTypes,theTranslator->trPublicTypes());
+      ctx->addMemberList(m_classDef,MemberListType_services,theTranslator->trServices());
+      ctx->addMemberList(m_classDef,MemberListType_interfaces,theTranslator->trInterfaces());
+      ctx->addMemberList(m_classDef,MemberListType_pubSlots,theTranslator->trPublicSlots());
+      ctx->addMemberList(m_classDef,MemberListType_signals,theTranslator->trSignals());
+      ctx->addMemberList(m_classDef,MemberListType_pubMethods,
+        m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trInstanceMethods()
+                                                   : theTranslator->trPublicMembers());
+      ctx->addMemberList(m_classDef,MemberListType_pubStaticMethods,
+        m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trClassMethods()
+                                                   : theTranslator->trStaticPublicMembers());
+      ctx->addMemberList(m_classDef,MemberListType_pubAttribs,theTranslator->trPublicAttribs());
+      ctx->addMemberList(m_classDef,MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs());
+      ctx->addMemberList(m_classDef,MemberListType_proTypes,theTranslator->trProtectedTypes());
+      ctx->addMemberList(m_classDef,MemberListType_proSlots,theTranslator->trProtectedSlots());
+      ctx->addMemberList(m_classDef,MemberListType_proMethods,theTranslator->trProtectedMembers());
+      ctx->addMemberList(m_classDef,MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers());
+      ctx->addMemberList(m_classDef,MemberListType_proAttribs,theTranslator->trProtectedAttribs());
+      ctx->addMemberList(m_classDef,MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs());
+      ctx->addMemberList(m_classDef,MemberListType_pacTypes,theTranslator->trPackageTypes());
+      ctx->addMemberList(m_classDef,MemberListType_pacMethods,theTranslator->trPackageMembers());
+      ctx->addMemberList(m_classDef,MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers());
+      ctx->addMemberList(m_classDef,MemberListType_pacAttribs,theTranslator->trPackageAttribs());
+      ctx->addMemberList(m_classDef,MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs());
+      ctx->addMemberList(m_classDef,MemberListType_properties,theTranslator->trProperties());
+      ctx->addMemberList(m_classDef,MemberListType_events,theTranslator->trEvents());
+      ctx->addMemberList(m_classDef,MemberListType_priTypes,theTranslator->trPrivateTypes());
+      ctx->addMemberList(m_classDef,MemberListType_priSlots,theTranslator->trPrivateSlots());
+      ctx->addMemberList(m_classDef,MemberListType_priMethods,theTranslator->trPrivateMembers());
+      ctx->addMemberList(m_classDef,MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers());
+      ctx->addMemberList(m_classDef,MemberListType_priAttribs,theTranslator->trPrivateAttribs());
+      ctx->addMemberList(m_classDef,MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs());
+      ctx->addMemberList(m_classDef,MemberListType_related,theTranslator->trRelatedFunctions());
+      return list;
+    }
+    void addMembers(MemberList &list,const ClassDef *cd,MemberListType lt) const
     {
       const MemberList *ml = cd->getMemberList(lt);
       if (ml)
       {
-        Cachable &cache = getCache();
         for (const auto &md : *ml)
         {
           if (md->isBriefSectionVisible())
           {
-            cache.allMembers.push_back(md);
+            list.push_back(md);
           }
         }
       }
     }
-    TemplateVariant members() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.members)
-      {
-        addMembers(m_classDef,MemberListType_pubTypes);
-        addMembers(m_classDef,MemberListType_services);
-        addMembers(m_classDef,MemberListType_interfaces);
-        addMembers(m_classDef,MemberListType_pubSlots);
-        addMembers(m_classDef,MemberListType_signals);
-        addMembers(m_classDef,MemberListType_pubMethods);
-        addMembers(m_classDef,MemberListType_pubStaticMethods);
-        addMembers(m_classDef,MemberListType_pubAttribs);
-        addMembers(m_classDef,MemberListType_pubStaticAttribs);
-        addMembers(m_classDef,MemberListType_proTypes);
-        addMembers(m_classDef,MemberListType_proSlots);
-        addMembers(m_classDef,MemberListType_proMethods);
-        addMembers(m_classDef,MemberListType_proStaticMethods);
-        addMembers(m_classDef,MemberListType_proAttribs);
-        addMembers(m_classDef,MemberListType_proStaticAttribs);
-        addMembers(m_classDef,MemberListType_pacTypes);
-        addMembers(m_classDef,MemberListType_pacMethods);
-        addMembers(m_classDef,MemberListType_pacStaticMethods);
-        addMembers(m_classDef,MemberListType_pacAttribs);
-        addMembers(m_classDef,MemberListType_pacStaticAttribs);
-        addMembers(m_classDef,MemberListType_properties);
-        addMembers(m_classDef,MemberListType_events);
-        addMembers(m_classDef,MemberListType_priTypes);
-        addMembers(m_classDef,MemberListType_priSlots);
-        addMembers(m_classDef,MemberListType_priMethods);
-        addMembers(m_classDef,MemberListType_priStaticMethods);
-        addMembers(m_classDef,MemberListType_priAttribs);
-        addMembers(m_classDef,MemberListType_priStaticAttribs);
-        addMembers(m_classDef,MemberListType_related);
-        cache.members.reset(MemberListContext::alloc(&cache.allMembers));
-      }
-      return cache.members.get();
-    }
-    TemplateVariant allMembersList() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.allMembersList)
-      {
-        AllMembersListContext *ml = AllMembersListContext::alloc(m_classDef->memberNameInfoLinkedMap());
-        cache.allMembersList.reset(ml);
-      }
-      return cache.allMembersList.get();
-    }
-    TemplateVariant allMembersFileName() const
-    {
-      return m_classDef->getMemberListFileName();
-    }
-    TemplateVariant memberGroups() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.memberGroups)
-      {
-        if (!m_classDef->getMemberGroups().empty())
-        {
-          cache.memberGroups.reset(MemberGroupListContext::alloc(m_classDef,relPathAsString(),m_classDef->getMemberGroups(),m_classDef->subGrouping()));
-        }
-        else
-        {
-          cache.memberGroups.reset(MemberGroupListContext::alloc());
-        }
-      }
-      return cache.memberGroups.get();
-    }
-    TemplateVariant additionalInheritedMembers() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.additionalInheritedMembers)
-      {
-        InheritedMemberInfoListContext *ctx = InheritedMemberInfoListContext::alloc();
-        ctx->addMemberList(m_classDef,MemberListType_pubTypes,theTranslator->trPublicTypes());
-        ctx->addMemberList(m_classDef,MemberListType_services,theTranslator->trServices());
-        ctx->addMemberList(m_classDef,MemberListType_interfaces,theTranslator->trInterfaces());
-        ctx->addMemberList(m_classDef,MemberListType_pubSlots,theTranslator->trPublicSlots());
-        ctx->addMemberList(m_classDef,MemberListType_signals,theTranslator->trSignals());
-        ctx->addMemberList(m_classDef,MemberListType_pubMethods,
-          m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trInstanceMethods()
-                                                     : theTranslator->trPublicMembers());
-        ctx->addMemberList(m_classDef,MemberListType_pubStaticMethods,
-          m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trClassMethods()
-                                                     : theTranslator->trStaticPublicMembers());
-        ctx->addMemberList(m_classDef,MemberListType_pubAttribs,theTranslator->trPublicAttribs());
-        ctx->addMemberList(m_classDef,MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs());
-        ctx->addMemberList(m_classDef,MemberListType_proTypes,theTranslator->trProtectedTypes());
-        ctx->addMemberList(m_classDef,MemberListType_proSlots,theTranslator->trProtectedSlots());
-        ctx->addMemberList(m_classDef,MemberListType_proMethods,theTranslator->trProtectedMembers());
-        ctx->addMemberList(m_classDef,MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers());
-        ctx->addMemberList(m_classDef,MemberListType_proAttribs,theTranslator->trProtectedAttribs());
-        ctx->addMemberList(m_classDef,MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs());
-        ctx->addMemberList(m_classDef,MemberListType_pacTypes,theTranslator->trPackageTypes());
-        ctx->addMemberList(m_classDef,MemberListType_pacMethods,theTranslator->trPackageMembers());
-        ctx->addMemberList(m_classDef,MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers());
-        ctx->addMemberList(m_classDef,MemberListType_pacAttribs,theTranslator->trPackageAttribs());
-        ctx->addMemberList(m_classDef,MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs());
-        ctx->addMemberList(m_classDef,MemberListType_properties,theTranslator->trProperties());
-        ctx->addMemberList(m_classDef,MemberListType_events,theTranslator->trEvents());
-        ctx->addMemberList(m_classDef,MemberListType_priTypes,theTranslator->trPrivateTypes());
-        ctx->addMemberList(m_classDef,MemberListType_priSlots,theTranslator->trPrivateSlots());
-        ctx->addMemberList(m_classDef,MemberListType_priMethods,theTranslator->trPrivateMembers());
-        ctx->addMemberList(m_classDef,MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers());
-        ctx->addMemberList(m_classDef,MemberListType_priAttribs,theTranslator->trPrivateAttribs());
-        ctx->addMemberList(m_classDef,MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs());
-        ctx->addMemberList(m_classDef,MemberListType_related,theTranslator->trRelatedFunctions());
-        cache.additionalInheritedMembers.reset(ctx);
-      }
-      return cache.additionalInheritedMembers.get();
-    }
-    TemplateVariant isSimple() const
-    {
-      return m_classDef->isSimple();
-    }
-    TemplateVariant categoryOf() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.categoryOf && m_classDef->categoryOf())
-      {
-        cache.categoryOf.reset(ClassContext::alloc(m_classDef->categoryOf()));
-      }
-      if (cache.categoryOf)
-      {
-        return cache.categoryOf.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
+    TemplateVariant createMembers() const
+    {
+      MemberList list(MemberListType_allMembersList,MemberListContainer::Class);
+      addMembers(list,m_classDef,MemberListType_pubTypes);
+      addMembers(list,m_classDef,MemberListType_services);
+      addMembers(list,m_classDef,MemberListType_interfaces);
+      addMembers(list,m_classDef,MemberListType_pubSlots);
+      addMembers(list,m_classDef,MemberListType_signals);
+      addMembers(list,m_classDef,MemberListType_pubMethods);
+      addMembers(list,m_classDef,MemberListType_pubStaticMethods);
+      addMembers(list,m_classDef,MemberListType_pubAttribs);
+      addMembers(list,m_classDef,MemberListType_pubStaticAttribs);
+      addMembers(list,m_classDef,MemberListType_proTypes);
+      addMembers(list,m_classDef,MemberListType_proSlots);
+      addMembers(list,m_classDef,MemberListType_proMethods);
+      addMembers(list,m_classDef,MemberListType_proStaticMethods);
+      addMembers(list,m_classDef,MemberListType_proAttribs);
+      addMembers(list,m_classDef,MemberListType_proStaticAttribs);
+      addMembers(list,m_classDef,MemberListType_pacTypes);
+      addMembers(list,m_classDef,MemberListType_pacMethods);
+      addMembers(list,m_classDef,MemberListType_pacStaticMethods);
+      addMembers(list,m_classDef,MemberListType_pacAttribs);
+      addMembers(list,m_classDef,MemberListType_pacStaticAttribs);
+      addMembers(list,m_classDef,MemberListType_properties);
+      addMembers(list,m_classDef,MemberListType_events);
+      addMembers(list,m_classDef,MemberListType_priTypes);
+      addMembers(list,m_classDef,MemberListType_priSlots);
+      addMembers(list,m_classDef,MemberListType_priMethods);
+      addMembers(list,m_classDef,MemberListType_priStaticMethods);
+      addMembers(list,m_classDef,MemberListType_priAttribs);
+      addMembers(list,m_classDef,MemberListType_priStaticAttribs);
+      addMembers(list,m_classDef,MemberListType_related);
+      return MemberListContext::alloc(list);
+    }
+    TemplateVariant createUsedFiles() const
+    {
+      return UsedFilesContext::alloc(m_classDef);
+    }
+    TemplateVariant createCategoryOf() const
+    {
+      return m_classDef->categoryOf() ?
+         TemplateVariant(ClassContext::alloc(m_classDef->categoryOf())) :
+         TemplateVariant(FALSE);
+    }
+    int createNumInheritanceNodes() const
+    {
+      return m_classDef->countInheritanceNodes();
     }
 
-  private:
     const ClassDef *m_classDef;
     struct Cachable : public DefinitionContext<ClassContext::Private>::Cachable
     {
-      Cachable(const ClassDef *cd) : DefinitionContext<ClassContext::Private>::Cachable(cd),
-                               inheritanceNodes(-1),
-                               allMembers(MemberListType_allMembersList,MemberListContainer::Class) { }
-      SharedPtr<IncludeInfoContext>     includeInfo;
-      SharedPtr<InheritanceListContext> inheritsList;
-      SharedPtr<InheritanceListContext> inheritedByList;
-      std::unique_ptr<DotClassGraph>          classGraph;
-      std::unique_ptr<DotClassGraph>          collaborationGraph;
-      SharedPtr<TemplateList>           classes;
-      SharedPtr<TemplateList>           innerClasses;
-      SharedPtr<MemberListInfoContext>  publicTypes;
-      SharedPtr<MemberListInfoContext>  publicMethods;
-      SharedPtr<MemberListInfoContext>  publicStaticMethods;
-      SharedPtr<MemberListInfoContext>  publicAttributes;
-      SharedPtr<MemberListInfoContext>  publicStaticAttributes;
-      SharedPtr<MemberListInfoContext>  publicSlots;
-      SharedPtr<MemberListInfoContext>  protectedTypes;
-      SharedPtr<MemberListInfoContext>  protectedMethods;
-      SharedPtr<MemberListInfoContext>  protectedStaticMethods;
-      SharedPtr<MemberListInfoContext>  protectedAttributes;
-      SharedPtr<MemberListInfoContext>  protectedStaticAttributes;
-      SharedPtr<MemberListInfoContext>  protectedSlots;
-      SharedPtr<MemberListInfoContext>  privateTypes;
-      SharedPtr<MemberListInfoContext>  privateMethods;
-      SharedPtr<MemberListInfoContext>  privateStaticMethods;
-      SharedPtr<MemberListInfoContext>  privateAttributes;
-      SharedPtr<MemberListInfoContext>  privateStaticAttributes;
-      SharedPtr<MemberListInfoContext>  privateSlots;
-      SharedPtr<MemberListInfoContext>  packageTypes;
-      SharedPtr<MemberListInfoContext>  packageMethods;
-      SharedPtr<MemberListInfoContext>  packageStaticMethods;
-      SharedPtr<MemberListInfoContext>  packageAttributes;
-      SharedPtr<MemberListInfoContext>  packageStaticAttributes;
-      SharedPtr<MemberListInfoContext>  unoIDLServices;
-      SharedPtr<MemberListInfoContext>  unoIDLInterfaces;
-      SharedPtr<MemberListInfoContext>  signals;
-      SharedPtr<MemberListInfoContext>  properties;
-      SharedPtr<MemberListInfoContext>  events;
-      SharedPtr<MemberListInfoContext>  friends;
-      SharedPtr<MemberListInfoContext>  related;
-      SharedPtr<MemberListInfoContext>  detailedTypedefs;
-      SharedPtr<MemberListInfoContext>  detailedEnums;
-      SharedPtr<MemberListInfoContext>  detailedServices;
-      SharedPtr<MemberListInfoContext>  detailedInterfaces;
-      SharedPtr<MemberListInfoContext>  detailedConstructors;
-      SharedPtr<MemberListInfoContext>  detailedMethods;
-      SharedPtr<MemberListInfoContext>  detailedRelated;
-      SharedPtr<MemberListInfoContext>  detailedVariables;
-      SharedPtr<MemberListInfoContext>  detailedProperties;
-      SharedPtr<MemberListInfoContext>  detailedEvents;
-      SharedPtr<MemberGroupListContext> memberGroups;
-      SharedPtr<AllMembersListContext>  allMembersList;
-      SharedPtr<ArgumentListContext>    typeConstraints;
-      SharedPtr<TemplateList>           examples;
-      SharedPtr<TemplateList>           templateDecls;
-      SharedPtr<InheritedMemberInfoListContext> additionalInheritedMembers;
-      SharedPtr<MemberListContext>      members;
-      SharedPtr<UsedFilesContext>       usedFiles;
-      SharedPtr<TemplateList>           exampleList;
-      SharedPtr<ClassContext>           categoryOf;
-      int                               inheritanceNodes;
-      MemberList                        allMembers;
+      CachedItem<TemplateVariant,  Private, &Private::createIncludeInfo>                includeInfo;
+      CachedItem<TemplateVariant,  Private, &Private::createInheritsList>               inheritsList;
+      CachedItem<TemplateVariant,  Private, &Private::createInheritedByList>            inheritedByList;
+      CachedItem<DotClassGraphPtr, Private, &Private::createClassGraph>                 classGraph;
+      CachedItem<DotClassGraphPtr, Private, &Private::createCollaborationGraph>         collaborationGraph;
+      CachedItem<TemplateVariant,  Private, &Private::createClasses>                    classes;
+      CachedItem<TemplateVariant,  Private, &Private::createInnerClasses>               innerClasses;
+      CachedItem<TemplateVariant,  Private, &Private::createPublicTypes>                publicTypes;
+      CachedItem<TemplateVariant,  Private, &Private::createPublicMethods>              publicMethods;
+      CachedItem<TemplateVariant,  Private, &Private::createPublicStaticMethods>        publicStaticMethods;
+      CachedItem<TemplateVariant,  Private, &Private::createPublicAttributes>           publicAttributes;
+      CachedItem<TemplateVariant,  Private, &Private::createPublicStaticAttributes>     publicStaticAttributes;
+      CachedItem<TemplateVariant,  Private, &Private::createPublicSlots>                publicSlots;
+      CachedItem<TemplateVariant,  Private, &Private::createProtectedTypes>             protectedTypes;
+      CachedItem<TemplateVariant,  Private, &Private::createProtectedMethods>           protectedMethods;
+      CachedItem<TemplateVariant,  Private, &Private::createProtectedStaticMethods>     protectedStaticMethods;
+      CachedItem<TemplateVariant,  Private, &Private::createProtectedAttributes>        protectedAttributes;
+      CachedItem<TemplateVariant,  Private, &Private::createProtectedStaticAttributes>  protectedStaticAttributes;
+      CachedItem<TemplateVariant,  Private, &Private::createProtectedSlots>             protectedSlots;
+      CachedItem<TemplateVariant,  Private, &Private::createPrivateTypes>               privateTypes;
+      CachedItem<TemplateVariant,  Private, &Private::createPrivateMethods>             privateMethods;
+      CachedItem<TemplateVariant,  Private, &Private::createPrivateStaticMethods>       privateStaticMethods;
+      CachedItem<TemplateVariant,  Private, &Private::createPrivateAttributes>          privateAttributes;
+      CachedItem<TemplateVariant,  Private, &Private::createPrivateStaticAttributes>    privateStaticAttributes;
+      CachedItem<TemplateVariant,  Private, &Private::createPrivateSlots>               privateSlots;
+      CachedItem<TemplateVariant,  Private, &Private::createPackageTypes>               packageTypes;
+      CachedItem<TemplateVariant,  Private, &Private::createPackageMethods>             packageMethods;
+      CachedItem<TemplateVariant,  Private, &Private::createPackageStaticMethods>       packageStaticMethods;
+      CachedItem<TemplateVariant,  Private, &Private::createPackageAttributes>          packageAttributes;
+      CachedItem<TemplateVariant,  Private, &Private::createPackageStaticAttributes>    packageStaticAttributes;
+      CachedItem<TemplateVariant,  Private, &Private::createUnoIDLServices>             unoIDLServices;
+      CachedItem<TemplateVariant,  Private, &Private::createUnoIDLInterfaces>           unoIDLInterfaces;
+      CachedItem<TemplateVariant,  Private, &Private::createSignals>                    signals;
+      CachedItem<TemplateVariant,  Private, &Private::createProperties>                 properties;
+      CachedItem<TemplateVariant,  Private, &Private::createEvents>                     events;
+      CachedItem<TemplateVariant,  Private, &Private::createFriends>                    friends;
+      CachedItem<TemplateVariant,  Private, &Private::createRelated>                    related;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedTypedefs>           detailedTypedefs;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedEnums>              detailedEnums;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedServices>           detailedServices;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedInterfaces>         detailedInterfaces;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedConstructors>       detailedConstructors;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedMethods>            detailedMethods;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedRelated>            detailedRelated;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedVariables>          detailedVariables;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedProperties>         detailedProperties;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedEvents>             detailedEvents;
+      CachedItem<TemplateVariant,  Private, &Private::createMemberGroups>               memberGroups;
+      CachedItem<TemplateVariant,  Private, &Private::createAllMembersList>             allMembersList;
+      CachedItem<TemplateVariant,  Private, &Private::createTypeConstraints>            typeConstraints;
+      CachedItem<TemplateVariant,  Private, &Private::createExamples>                   examples;
+      CachedItem<TemplateVariant,  Private, &Private::createTemplateDecls>              templateDecls;
+      CachedItem<TemplateVariant,  Private, &Private::createAdditionalInheritedMembers> additionalInheritedMembers;
+      CachedItem<TemplateVariant,  Private, &Private::createMembers>                    members;
+      CachedItem<TemplateVariant,  Private, &Private::createUsedFiles>                  usedFiles;
+      CachedItem<TemplateVariant,  Private, &Private::createCategoryOf>                 categoryOf;
+      CachedItem<int,              Private, &Private::createNumInheritanceNodes>        numInheritanceNodes;
     };
-    Cachable &getCache() const
-    {
-      Cachable *c = static_cast<Cachable*>(m_classDef->cookie());
-      assert(c!=0);
-      return *c;
-    }
-    static PropertyMapper<ClassContext::Private> s_inst;
+    Cachable m_cachable;
+   static const PropertyMap<ClassContext::Private> s_inst;
+};
+
+//%% struct Class(Symbol): class information
+//%% {
+const PropertyMap<ClassContext::Private> ClassContext::Private::s_inst {
+  BASE_PROPERTIES,
+  {  "title",                     &Private::title },
+  {  "highlight",                 &Private::highlight },
+  {  "subhighlight",              &Private::subHighlight },
+  {  "hasDetails",                &Private::hasDetails },
+  {  "generatedFromFiles",        &Private::generatedFromFiles },
+  {  "usedFiles",                 &Private::usedFiles },
+  {  "hasInheritanceDiagram",     &Private::hasInheritanceDiagram },
+  {  "inheritanceDiagram",        &Private::inheritanceDiagram },
+  {  "hasCollaborationDiagram",   &Private::hasCollaborationDiagram },
+  {  "collaborationDiagram",      &Private::collaborationDiagram },
+  {  "includeInfo",               &Private::includeInfo },
+  {  "inherits",                  &Private::inherits },
+  {  "inheritedBy",               &Private::inheritedBy },
+  {  "unoIDLServices",            &Private::unoIDLServices },
+  {  "unoIDLInterfaces",          &Private::unoIDLInterfaces },
+  {  "signals",                   &Private::signals },
+  {  "publicTypes",               &Private::publicTypes },
+  {  "publicMethods",             &Private::publicMethods },
+  {  "publicStaticMethods",       &Private::publicStaticMethods },
+  {  "publicAttributes",          &Private::publicAttributes },
+  {  "publicStaticAttributes",    &Private::publicStaticAttributes },
+  {  "publicSlots",               &Private::publicSlots },
+  {  "protectedTypes",            &Private::protectedTypes },
+  {  "protectedMethods",          &Private::protectedMethods },
+  {  "protectedStaticMethods",    &Private::protectedStaticMethods },
+  {  "protectedAttributes",       &Private::protectedAttributes },
+  {  "protectedStaticAttributes", &Private::protectedStaticAttributes },
+  {  "protectedSlots",            &Private::protectedSlots },
+  {  "privateTypes",              &Private::privateTypes },
+  {  "privateMethods",            &Private::privateMethods },
+  {  "privateStaticMethods",      &Private::privateStaticMethods },
+  {  "privateAttributes",         &Private::privateAttributes },
+  {  "privateStaticAttributes",   &Private::privateStaticAttributes },
+  {  "privateSlots",              &Private::privateSlots },
+  {  "packageTypes",              &Private::packageTypes },
+  {  "packageMethods",            &Private::packageMethods },
+  {  "packageStaticMethods",      &Private::packageStaticMethods },
+  {  "packageAttributes",         &Private::packageAttributes },
+  {  "packageStaticAttributes",   &Private::packageStaticAttributes },
+  {  "properties",                &Private::properties },
+  {  "events",                    &Private::events },
+  {  "friends",                   &Private::friends },
+  {  "related",                   &Private::related },
+  {  "detailedTypedefs",          &Private::detailedTypedefs },
+  {  "detailedEnums",             &Private::detailedEnums },
+  {  "detailedServices",          &Private::detailedServices },
+  {  "detailedInterfaces",        &Private::detailedInterfaces },
+  {  "detailedConstructors",      &Private::detailedConstructors },
+  {  "detailedMethods",           &Private::detailedMethods },
+  {  "detailedRelated",           &Private::detailedRelated },
+  {  "detailedVariables",         &Private::detailedVariables },
+  {  "detailedProperties",        &Private::detailedProperties },
+  {  "detailedEvents",            &Private::detailedEvents },
+  {  "classes",                   &Private::classes },
+  {  "innerClasses",              &Private::innerClasses },
+  {  "compoundType",              &Private::compoundType },
+  {  "templateDecls",             &Private::templateDecls },
+  {  "typeConstraints",           &Private::typeConstraints },
+  {  "examples",                  &Private::examples },
+  {  "members",                   &Private::members },
+  {  "allMembersList",            &Private::allMembersList },
+  {  "allMembersFileName",        &Private::allMembersFileName },
+  {  "memberGroups",              &Private::memberGroups },
+  {  "additionalInheritedMembers",&Private::additionalInheritedMembers },
+  {  "isSimple",                  &Private::isSimple },
+  {  "categoryOf",                &Private::categoryOf }
 };
 //%% }
 
-PropertyMapper<ClassContext::Private> ClassContext::Private::s_inst;
+//PropertyMapper<ClassContext::Private> ClassContext::Private::s_inst;
 
-ClassContext::ClassContext(const ClassDef *cd) : RefCountedContext("ClassContext")
+ClassContext::ClassContext(const ClassDef *cd) : p(std::make_unique<Private>(cd))
 {
-  //printf("ClassContext::ClassContext(%s)\n",cd?qPrint(cd->name()):"<none>");
-  p = new Private(cd);
 }
 
 ClassContext::~ClassContext()
 {
-  delete p;
 }
 
 TemplateVariant ClassContext::get(const QCString &n) const
@@ -2724,292 +2488,239 @@ StringVector ClassContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct Namespace(Symbol): namespace information
-//%% {
 class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Private>
 {
   public:
     Private(const NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>(nd),
                                 m_namespaceDef(nd)
     {
-      static bool init=FALSE;
-      if (!init)
-      {
-        addBaseProperties(s_inst);
-        s_inst.addProperty("title",                &Private::title);
-        s_inst.addProperty("highlight",            &Private::highlight);
-        s_inst.addProperty("subhighlight",         &Private::subHighlight);
-        s_inst.addProperty("compoundType",         &Private::compoundType);
-        s_inst.addProperty("hasDetails",           &Private::hasDetails);
-        s_inst.addProperty("classes",              &Private::classes);
-        //s_inst.addProperty("interfaces",           &Private::interfaces);
-        s_inst.addProperty("namespaces",           &Private::namespaces);
-        s_inst.addProperty("constantgroups",       &Private::constantgroups);
-        s_inst.addProperty("typedefs",             &Private::typedefs);
-        s_inst.addProperty("sequences",            &Private::sequences);
-        s_inst.addProperty("dictionaries",         &Private::dictionaries);
-        s_inst.addProperty("enums",                &Private::enums);
-        s_inst.addProperty("functions",            &Private::functions);
-        s_inst.addProperty("variables",            &Private::variables);
-        s_inst.addProperty("memberGroups",         &Private::memberGroups);
-        s_inst.addProperty("detailedTypedefs",     &Private::detailedTypedefs);
-        s_inst.addProperty("detailedSequences",    &Private::detailedSequences);
-        s_inst.addProperty("detailedDictionaries", &Private::detailedDictionaries);
-        s_inst.addProperty("detailedEnums",        &Private::detailedEnums);
-        s_inst.addProperty("detailedFunctions",    &Private::detailedFunctions);
-        s_inst.addProperty("detailedVariables",    &Private::detailedVariables);
-        s_inst.addProperty("inlineClasses",        &Private::inlineClasses);
-        init=TRUE;
-      }
-      if (!nd->cookie()) { nd->setCookie(new NamespaceContext::Private::Cachable(nd)); }
     }
     virtual ~Private() {}
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant title() const
-    {
-      return TemplateVariant(m_namespaceDef->title());
-    }
-    TemplateVariant highlight() const
-    {
-      return TemplateVariant("namespaces");
-    }
-    TemplateVariant subHighlight() const
-    {
-      return TemplateVariant("");
-    }
-    TemplateVariant compoundType() const
-    {
-      return m_namespaceDef->compoundTypeString();
-    }
-    TemplateVariant hasDetails() const
-    {
-      return m_namespaceDef->hasDetailedDescription();
-    }
-    TemplateVariant classes() const
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant title() const                { return TemplateVariant(m_namespaceDef->title()); }
+    TemplateVariant highlight() const            { return TemplateVariant("namespaces"); }
+    TemplateVariant subHighlight() const         { return TemplateVariant(""); }
+    TemplateVariant compoundType() const         { return m_namespaceDef->compoundTypeString(); }
+    TemplateVariant hasDetails() const           { return m_namespaceDef->hasDetailedDescription(); }
+    TemplateVariant classes() const              { return m_cachable.classes.get(this); }
+    TemplateVariant namespaces() const           { return m_cachable.namespaces.get(this); }
+    TemplateVariant constantgroups() const       { return m_cachable.constantgroups.get(this); }
+    TemplateVariant typedefs() const             { return m_cachable.typedefs.get(this); }
+    TemplateVariant sequences() const            { return m_cachable.sequences.get(this); }
+    TemplateVariant dictionaries() const         { return m_cachable.dictionaries.get(this); }
+    TemplateVariant enums() const                { return m_cachable.enums.get(this); }
+    TemplateVariant functions() const            { return m_cachable.functions.get(this); }
+    TemplateVariant variables() const            { return m_cachable.variables.get(this); }
+    TemplateVariant memberGroups() const         { return m_cachable.memberGroups.get(this); }
+    TemplateVariant detailedTypedefs() const     { return m_cachable.detailedTypedefs.get(this); }
+    TemplateVariant detailedSequences() const    { return m_cachable.detailedSequences.get(this); }
+    TemplateVariant detailedDictionaries() const { return m_cachable.detailedDictionaries.get(this); }
+    TemplateVariant detailedEnums() const        { return m_cachable.detailedEnums.get(this); }
+    TemplateVariant detailedFunctions() const    { return m_cachable.detailedFunctions.get(this); }
+    TemplateVariant detailedVariables() const    { return m_cachable.detailedVariables.get(this); }
+    TemplateVariant inlineClasses() const        { return m_cachable.inlineClasses.get(this); }
+
+  private:
+    TemplateVariant createClasses() const
     {
-      Cachable &cache = getCache();
-      if (!cache.classes)
+      static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+      TemplateVariantList classList;
+      classList.reserve(m_namespaceDef->getClasses().size());
+      for (const auto &cd : m_namespaceDef->getClasses())
       {
-        static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
-        TemplateList *classList = TemplateList::alloc();
-        for (const auto &cd : m_namespaceDef->getClasses())
+        if (sliceOpt && (cd->compoundType()==ClassDef::Struct    ||
+                         cd->compoundType()==ClassDef::Interface ||
+                         cd->compoundType()==ClassDef::Exception))
         {
-          if (sliceOpt && (cd->compoundType()==ClassDef::Struct    ||
-                           cd->compoundType()==ClassDef::Interface ||
-                           cd->compoundType()==ClassDef::Exception))
-          {
-            continue; // These types appear in their own sections.
-          }
-          if (cd->visibleInParentsDeclList())
-          {
-            classList->append(ClassContext::alloc(cd));
-          }
+          continue; // These types appear in their own sections.
         }
-        cache.classes.reset(classList);
-      }
-      return cache.classes.get();
-    }
-    TemplateVariant namespaces() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.namespaces)
-      {
-        TemplateList *namespaceList = TemplateList::alloc();
-        for (const auto &nd : m_namespaceDef->getNamespaces())
+        if (cd->visibleInParentsDeclList())
         {
-          if (nd->isLinkable() && !nd->isConstantGroup())
-          {
-            namespaceList->append(NamespaceContext::alloc(nd));
-          }
+          classList.push_back(ClassContext::alloc(cd));
         }
-        cache.namespaces.reset(namespaceList);
       }
-      return cache.namespaces.get();
+      return TemplateImmutableList::alloc(classList);
     }
-    TemplateVariant constantgroups() const
+    TemplateVariant createNamespaces() const
     {
-      Cachable &cache = getCache();
-      if (!cache.constantgroups)
+      TemplateVariantList list;
+      list.reserve(m_namespaceDef->getNamespaces().size());
+      for (const auto &nd : m_namespaceDef->getNamespaces())
       {
-        TemplateList *namespaceList = TemplateList::alloc();
-        for (const auto &nd : m_namespaceDef->getNamespaces())
+        if (nd->isLinkable() && !nd->isConstantGroup())
         {
-          if (nd->isLinkable() && nd->isConstantGroup())
-          {
-            namespaceList->append(NamespaceContext::alloc(nd));
-          }
+          list.push_back(NamespaceContext::alloc(nd));
         }
-        cache.constantgroups.reset(namespaceList);
       }
-      return cache.constantgroups.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list,
-                                  MemberListType type,const QCString &title,bool=FALSE) const
+    TemplateVariant createConstantgroups() const
     {
-      if (!list)
+      TemplateVariantList list;
+      list.reserve(m_namespaceDef->getNamespaces().size());
+      for (const auto &nd : m_namespaceDef->getNamespaces())
       {
-        const MemberList *ml = m_namespaceDef->getMemberList(type);
-        if (ml)
+        if (nd->isLinkable() && nd->isConstantGroup())
         {
-          list.reset(MemberListInfoContext::alloc(m_namespaceDef,relPathAsString(),ml,title,""));
+          list.push_back(NamespaceContext::alloc(nd));
         }
       }
-      if (list)
-      {
-        return list.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant typedefs() const
+    TemplateVariant createMemberList(MemberListType type,const QCString &title) const
     {
-      return getMemberList(getCache().typedefs,MemberListType_decTypedefMembers,theTranslator->trTypedefs());
+      const MemberList *ml = m_namespaceDef->getMemberList(type);
+      return ml ? TemplateVariant(MemberListInfoContext::alloc(m_namespaceDef,relPathAsString(),ml,title,""))
+                : TemplateVariant(false);
     }
-    TemplateVariant sequences() const
+    TemplateVariant createTypedefs() const
     {
-      return getMemberList(getCache().sequences,MemberListType_decSequenceMembers,theTranslator->trSequences());
+      return createMemberList(MemberListType_decTypedefMembers,theTranslator->trTypedefs());
     }
-    TemplateVariant dictionaries() const
+    TemplateVariant createSequences() const
     {
-      return getMemberList(getCache().dictionaries,MemberListType_decDictionaryMembers,theTranslator->trDictionaries());
+      return createMemberList(MemberListType_decSequenceMembers,theTranslator->trSequences());
     }
-    TemplateVariant enums() const
+    TemplateVariant createDictionaries() const
     {
-      return getMemberList(getCache().enums,MemberListType_decEnumMembers,theTranslator->trEnumerations());
+      return createMemberList(MemberListType_decDictionaryMembers,theTranslator->trDictionaries());
     }
-    TemplateVariant functions() const
+    TemplateVariant createEnums() const
     {
-      QCString title = theTranslator->trFunctions();
-      SrcLangExt lang = m_namespaceDef->getLanguage();
-      if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprograms();
-      else if (lang==SrcLangExt_VHDL) title=theTranslator->trFunctionAndProc();
-      return getMemberList(getCache().functions,MemberListType_decFuncMembers,title);
+      return createMemberList(MemberListType_decEnumMembers,theTranslator->trEnumerations());
     }
-    TemplateVariant variables() const
+    TemplateVariant createFunctions() const
     {
-      static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
-      return getMemberList(getCache().variables,MemberListType_decVarMembers,
-                           sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables());
+      SrcLangExt lang = m_namespaceDef->getLanguage();
+      return createMemberList(MemberListType_decFuncMembers,lang==SrcLangExt_Fortran ? theTranslator->trSubprograms() :
+                                                            lang==SrcLangExt_VHDL    ? theTranslator->trFunctionAndProc() :
+                                                                                       theTranslator->trFunctions());
     }
-    TemplateVariant memberGroups() const
+    TemplateVariant createVariables() const
     {
-      Cachable &cache = getCache();
-      if (!cache.memberGroups)
-      {
-        if (!m_namespaceDef->getMemberGroups().empty())
-        {
-          cache.memberGroups.reset(MemberGroupListContext::alloc(m_namespaceDef,relPathAsString(),m_namespaceDef->getMemberGroups(),m_namespaceDef->subGrouping()));
-        }
-        else
-        {
-          cache.memberGroups.reset(MemberGroupListContext::alloc());
-        }
-      }
-      return cache.memberGroups.get();
+      static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+      return createMemberList(MemberListType_decVarMembers, sliceOpt ? theTranslator->trConstants() :
+                                                                       theTranslator->trVariables());
     }
-    TemplateVariant detailedTypedefs() const
+    TemplateVariant createDetailedTypedefs() const
     {
-      return getMemberList(getCache().detailedTypedefs,MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
+      return createMemberList(MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
     }
-    TemplateVariant detailedSequences() const
+    TemplateVariant createDetailedSequences() const
     {
-      return getMemberList(getCache().detailedSequences,MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation());
+      return createMemberList(MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation());
     }
-    TemplateVariant detailedDictionaries() const
+    TemplateVariant createDetailedDictionaries() const
     {
-      return getMemberList(getCache().detailedDictionaries,MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation());
+      return createMemberList(MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation());
     }
-    TemplateVariant detailedEnums() const
+    TemplateVariant createDetailedEnums() const
     {
-      return getMemberList(getCache().detailedEnums,MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
+      return createMemberList(MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
     }
-    TemplateVariant detailedFunctions() const
+    TemplateVariant createDetailedFunctions() const
     {
-      QCString title = theTranslator->trFunctionDocumentation();
       SrcLangExt lang = m_namespaceDef->getLanguage();
-      if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprogramDocumentation();
-      return getMemberList(getCache().detailedFunctions,MemberListType_docFuncMembers,title);
+      return createMemberList(MemberListType_docFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprogramDocumentation() :
+                                                                                        theTranslator->trFunctionDocumentation());
     }
-    TemplateVariant detailedVariables() const
+    TemplateVariant createDetailedVariables() const
     {
       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
-      return getMemberList(getCache().detailedVariables,MemberListType_docVarMembers,
-                           sliceOpt ? theTranslator->trConstantDocumentation() :
-                           theTranslator->trVariableDocumentation());
+      return createMemberList(MemberListType_docVarMembers, sliceOpt ? theTranslator->trConstantDocumentation() :
+                                                                       theTranslator->trVariableDocumentation());
+    }
+    TemplateVariant createMemberGroups() const
+    {
+      return !m_namespaceDef->getMemberGroups().empty() ?
+              MemberGroupListContext::alloc(m_namespaceDef,relPathAsString(),
+                                                            m_namespaceDef->getMemberGroups(),
+                                                            m_namespaceDef->subGrouping()) :
+              MemberGroupListContext::alloc();
     }
-    TemplateVariant inlineClasses() const
+    TemplateVariant createInlineClasses() const
     {
-      Cachable &cache = getCache();
-      if (!cache.inlineClasses)
+      TemplateVariantList list;
+      list.reserve(m_namespaceDef->getClasses().size());
+      for (const auto &cd : m_namespaceDef->getClasses())
       {
-        TemplateList *classList = TemplateList::alloc();
-        for (const auto &cd : m_namespaceDef->getClasses())
+        if (!cd->isAnonymous() &&
+            cd->isLinkableInProject() &&
+            cd->isEmbeddedInOuterScope() &&
+            cd->partOfGroups().empty())
         {
-          if (!cd->isAnonymous() &&
-              cd->isLinkableInProject() &&
-              cd->isEmbeddedInOuterScope() &&
-              cd->partOfGroups().empty())
-          {
-            classList->append(ClassContext::alloc(cd));
-          }
+          list.push_back(ClassContext::alloc(cd));
         }
-        cache.inlineClasses.reset(classList);
       }
-      return cache.inlineClasses.get();
+      return TemplateImmutableList::alloc(list);
     }
-  private:
+
     const NamespaceDef *m_namespaceDef;
     struct Cachable : public DefinitionContext<NamespaceContext::Private>::Cachable
     {
-      Cachable(const NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>::Cachable(nd) {}
-      SharedPtr<TemplateList>               classes;
-      SharedPtr<TemplateList>               interfaces;
-      SharedPtr<TemplateList>               namespaces;
-      SharedPtr<TemplateList>               constantgroups;
-      SharedPtr<MemberListInfoContext>      typedefs;
-      SharedPtr<MemberListInfoContext>      sequences;
-      SharedPtr<MemberListInfoContext>      dictionaries;
-      SharedPtr<MemberListInfoContext>      enums;
-      SharedPtr<MemberListInfoContext>      functions;
-      SharedPtr<MemberListInfoContext>      variables;
-      SharedPtr<MemberGroupListContext>     memberGroups;
-      SharedPtr<MemberListInfoContext>      detailedTypedefs;
-      SharedPtr<MemberListInfoContext>      detailedSequences;
-      SharedPtr<MemberListInfoContext>      detailedDictionaries;
-      SharedPtr<MemberListInfoContext>      detailedEnums;
-      SharedPtr<MemberListInfoContext>      detailedFunctions;
-      SharedPtr<MemberListInfoContext>      detailedVariables;
-      SharedPtr<TemplateList>               inlineClasses;
+      CachedItem<TemplateVariant,  Private, &Private::createClasses>              classes;
+      CachedItem<TemplateVariant,  Private, &Private::createNamespaces>           namespaces;
+      CachedItem<TemplateVariant,  Private, &Private::createConstantgroups>       constantgroups;
+      CachedItem<TemplateVariant,  Private, &Private::createTypedefs>             typedefs;
+      CachedItem<TemplateVariant,  Private, &Private::createSequences>            sequences;
+      CachedItem<TemplateVariant,  Private, &Private::createDictionaries>         dictionaries;
+      CachedItem<TemplateVariant,  Private, &Private::createEnums>                enums;
+      CachedItem<TemplateVariant,  Private, &Private::createFunctions>            functions;
+      CachedItem<TemplateVariant,  Private, &Private::createVariables>            variables;
+      CachedItem<TemplateVariant,  Private, &Private::createMemberGroups>         memberGroups;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedTypedefs>     detailedTypedefs;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedSequences>    detailedSequences;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedDictionaries> detailedDictionaries;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedEnums>        detailedEnums;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedFunctions>    detailedFunctions;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedVariables>    detailedVariables;
+      CachedItem<TemplateVariant,  Private, &Private::createInlineClasses>        inlineClasses;
     };
-    Cachable &getCache() const
-    {
-      Cachable *c = static_cast<Cachable*>(m_namespaceDef->cookie());
-      assert(c!=0);
-      return *c;
-    }
-    static PropertyMapper<NamespaceContext::Private> s_inst;
+    Cachable m_cachable;
+    static const PropertyMap<NamespaceContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<NamespaceContext::Private> NamespaceContext::Private::s_inst;
+//%% struct Namespace(Symbol): namespace information
+//%% {
+const PropertyMap<NamespaceContext::Private> NamespaceContext::Private::s_inst {
+  BASE_PROPERTIES,
+  {  "title",                &Private::title },
+  {  "highlight",            &Private::highlight },
+  {  "subhighlight",         &Private::subHighlight },
+  {  "compoundType",         &Private::compoundType },
+  {  "hasDetails",           &Private::hasDetails },
+  {  "classes",              &Private::classes },
+  {  "namespaces",           &Private::namespaces },
+  {  "constantgroups",       &Private::constantgroups },
+  {  "typedefs",             &Private::typedefs },
+  {  "sequences",            &Private::sequences },
+  {  "dictionaries",         &Private::dictionaries },
+  {  "enums",                &Private::enums },
+  {  "functions",            &Private::functions },
+  {  "variables",            &Private::variables },
+  {  "memberGroups",         &Private::memberGroups },
+  {  "detailedTypedefs",     &Private::detailedTypedefs },
+  {  "detailedSequences",    &Private::detailedSequences },
+  {  "detailedDictionaries", &Private::detailedDictionaries },
+  {  "detailedEnums",        &Private::detailedEnums },
+  {  "detailedFunctions",    &Private::detailedFunctions },
+  {  "detailedVariables",    &Private::detailedVariables },
+  {  "inlineClasses",        &Private::inlineClasses }
+};
+//%% }
 
-NamespaceContext::NamespaceContext(const NamespaceDef *nd) : RefCountedContext("NamespaceContext")
+NamespaceContext::NamespaceContext(const NamespaceDef *nd) : p(std::make_unique<Private>(nd))
 {
-  p = new Private(nd);
 }
 
 NamespaceContext::~NamespaceContext()
 {
-  delete p;
 }
 
 TemplateVariant NamespaceContext::get(const QCString &n) const
@@ -3024,110 +2735,56 @@ StringVector NamespaceContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct File(Symbol): file information
-//%% {
 class FileContext::Private : public DefinitionContext<FileContext::Private>
 {
   public:
     Private(const FileDef *fd) : DefinitionContext<FileContext::Private>(fd) , m_fileDef(fd)
     {
       if (fd==0) abort();
-      static bool init=FALSE;
-      if (!init)
-      {
-        addBaseProperties(s_inst);
-        s_inst.addProperty("title",                     &Private::title);
-        s_inst.addProperty("highlight",                 &Private::highlight);
-        s_inst.addProperty("subhighlight",              &Private::subHighlight);
-        s_inst.addProperty("versionInfo",               &Private::versionInfo);
-        s_inst.addProperty("includeList",               &Private::includeList);
-        s_inst.addProperty("hasIncludeGraph",           &Private::hasIncludeGraph);
-        s_inst.addProperty("hasIncludedByGraph",        &Private::hasIncludedByGraph);
-        s_inst.addProperty("includeGraph",              &Private::includeGraph);
-        s_inst.addProperty("includedByGraph",           &Private::includedByGraph);
-        s_inst.addProperty("hasDetails",                &Private::hasDetails);
-        s_inst.addProperty("hasSourceFile",             &Private::hasSourceFile);
-        s_inst.addProperty("sources",                   &Private::sources);
-        s_inst.addProperty("version",                   &Private::version);
-        s_inst.addProperty("classes",                   &Private::classes);
-        s_inst.addProperty("namespaces",                &Private::namespaces);
-        s_inst.addProperty("constantgroups",            &Private::constantgroups);
-        s_inst.addProperty("macros",                    &Private::macros);
-        s_inst.addProperty("typedefs",                  &Private::typedefs);
-        s_inst.addProperty("sequences",                 &Private::sequences);
-        s_inst.addProperty("dictionaries",              &Private::dictionaries);
-        s_inst.addProperty("enums",                     &Private::enums);
-        s_inst.addProperty("functions",                 &Private::functions);
-        s_inst.addProperty("variables",                 &Private::variables);
-        s_inst.addProperty("memberGroups",              &Private::memberGroups);
-        s_inst.addProperty("detailedMacros",            &Private::detailedMacros);
-        s_inst.addProperty("detailedTypedefs",          &Private::detailedTypedefs);
-        s_inst.addProperty("detailedSequences",         &Private::detailedSequences);
-        s_inst.addProperty("detailedDictionaries",      &Private::detailedDictionaries);
-        s_inst.addProperty("detailedEnums",             &Private::detailedEnums);
-        s_inst.addProperty("detailedFunctions",         &Private::detailedFunctions);
-        s_inst.addProperty("detailedVariables",         &Private::detailedVariables);
-        s_inst.addProperty("inlineClasses",             &Private::inlineClasses);
-        s_inst.addProperty("compoundType",              &Private::compoundType);
-        init=TRUE;
-      }
-      if (!fd->cookie()) { fd->setCookie(new FileContext::Private::Cachable(fd)); }
     }
     virtual ~Private() {}
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant title() const
-    {
-      return m_fileDef->title();
-    }
-    TemplateVariant highlight() const
-    {
-      return TemplateVariant("files");
-    }
-    TemplateVariant subHighlight() const
-    {
-      return TemplateVariant("");
-    }
-    TemplateVariant versionInfo() const
-    {
-      return m_fileDef->getVersion();
-    }
-    TemplateVariant includeList() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.includeInfoList && !m_fileDef->includeFileList().empty())
-      {
-        cache.includeInfoList.reset(IncludeInfoListContext::alloc(
-              m_fileDef->includeFileList(),m_fileDef->getLanguage()));
-      }
-      if (cache.includeInfoList)
-      {
-        return cache.includeInfoList.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
-    }
-    DotInclDepGraph *getIncludeGraph() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.includeGraph)
-      {
-        cache.includeGraph.reset(new DotInclDepGraph(m_fileDef,FALSE));
-      }
-      return cache.includeGraph.get();
-    }
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const { return s_inst.fields(); }
+
+    // Property getters
+    TemplateVariant title() const                 { return m_fileDef->title(); }
+    TemplateVariant highlight() const             { return TemplateVariant("files"); }
+    TemplateVariant subHighlight() const          { return TemplateVariant(""); }
+    TemplateVariant versionInfo() const           { return m_fileDef->getVersion(); }
+    TemplateVariant includeList() const           { return m_cachable.includeList.get(this); }
+    TemplateVariant hasDetails() const            { return m_fileDef->hasDetailedDescription(); }
+    TemplateVariant hasSourceFile() const         { return m_fileDef->generateSourceFile(); }
+    TemplateVariant sources() const               { return m_cachable.sources.get(this); }
+    TemplateVariant version() const               { return m_fileDef->fileVersion(); }
+    TemplateVariant classes() const               { return m_cachable.classes.get(this); }
+    TemplateVariant namespaces() const            { return m_cachable.namespaces.get(this); }
+    TemplateVariant constantgroups() const        { return m_cachable.constantgroups.get(this); }
+    TemplateVariant macros() const                { return m_cachable.macros.get(this); }
+    TemplateVariant typedefs() const              { return m_cachable.typedefs.get(this); }
+    TemplateVariant sequences() const             { return m_cachable.sequences.get(this); }
+    TemplateVariant dictionaries() const          { return m_cachable.dictionaries.get(this); }
+    TemplateVariant enums() const                 { return m_cachable.enums.get(this); }
+    TemplateVariant functions() const             { return m_cachable.functions.get(this); }
+    TemplateVariant variables() const             { return m_cachable.variables.get(this); }
+    TemplateVariant memberGroups() const          { return m_cachable.memberGroups.get(this); }
+    TemplateVariant detailedMacros() const        { return m_cachable.detailedMacros.get(this); }
+    TemplateVariant detailedTypedefs() const      { return m_cachable.detailedTypedefs.get(this); }
+    TemplateVariant detailedSequences() const     { return m_cachable.detailedSequences.get(this); }
+    TemplateVariant detailedDictionaries() const  { return m_cachable.detailedDictionaries.get(this); }
+    TemplateVariant detailedEnums() const         { return m_cachable.detailedEnums.get(this); }
+    TemplateVariant detailedFunctions() const     { return m_cachable.detailedFunctions.get(this); }
+    TemplateVariant detailedVariables() const     { return m_cachable.detailedVariables.get(this); }
+    TemplateVariant inlineClasses() const         { return m_cachable.inlineClasses.get(this); }
+    TemplateVariant compoundType() const          { return theTranslator->trFile(FALSE,TRUE); }
+    DotInclDepGraphPtr getIncludeGraph() const    { return m_cachable.includeGraph.get(this); }
+    DotInclDepGraphPtr getIncludedByGraph() const { return m_cachable.includedByGraph.get(this); }
+
     TemplateVariant hasIncludeGraph() const
     {
       static bool haveDot = Config_getBool(HAVE_DOT);
-      DotInclDepGraph *incGraph = getIncludeGraph();
+      DotInclDepGraphPtr incGraph = getIncludeGraph();
       return (haveDot && !incGraph->isTooBig() && !incGraph->isTrivial());
     }
     TemplateVariant includeGraph() const
@@ -3136,14 +2793,14 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
       TextStream t;
       if (haveDot)
       {
-        DotInclDepGraph *cg = getIncludeGraph();
+        DotInclDepGraphPtr cg = getIncludeGraph();
         switch (g_globals.outputFormat)
         {
           case ContextOutputFormat_Html:
             {
               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
                   g_globals.outputDir,
-                  g_globals.outputDir+Portable::pathSeparator()+m_fileDef->getOutputFileBase()+Doxygen::htmlFileExtension,
+                  g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_fileDef->getOutputFileBase()),
                   relPathAsString(),TRUE,g_globals.dynSectionId
                   );
             }
@@ -3166,19 +2823,10 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
       }
       return TemplateVariant(t.str().c_str(),TRUE);
     }
-    DotInclDepGraph *getIncludedByGraph() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.includedByGraph)
-      {
-        cache.includedByGraph.reset(new DotInclDepGraph(m_fileDef,TRUE));
-      }
-      return cache.includedByGraph.get();
-    }
     TemplateVariant hasIncludedByGraph() const
     {
       static bool haveDot = Config_getBool(HAVE_DOT);
-      DotInclDepGraph *incGraph = getIncludedByGraph();
+      DotInclDepGraphPtr incGraph = getIncludedByGraph();
       return (haveDot && !incGraph->isTooBig() && !incGraph->isTrivial());
     }
     TemplateVariant includedByGraph() const
@@ -3187,14 +2835,14 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
       TextStream t;
       if (haveDot)
       {
-        DotInclDepGraph *cg = getIncludedByGraph();
+        DotInclDepGraphPtr cg = getIncludedByGraph();
         switch (g_globals.outputFormat)
         {
           case ContextOutputFormat_Html:
             {
               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
                   g_globals.outputDir,
-                  g_globals.outputDir+Portable::pathSeparator()+m_fileDef->getOutputFileBase()+Doxygen::htmlFileExtension,
+                  g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_fileDef->getOutputFileBase()),
                   relPathAsString(),TRUE,g_globals.dynSectionId
                   );
             }
@@ -3217,260 +2865,239 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
       }
       return TemplateVariant(t.str().c_str(),TRUE);
     }
-    TemplateVariant hasDetails() const
+
+  private:
+
+    TemplateVariant createIncludeList() const
     {
-      return m_fileDef->hasDetailedDescription();
+      return !m_fileDef->includeFileList().empty() ?
+        TemplateVariant(IncludeInfoListContext::alloc(m_fileDef->includeFileList(),m_fileDef->getLanguage())) :
+        TemplateVariant(false);
     }
-    TemplateVariant hasSourceFile() const
+    DotInclDepGraphPtr createIncludeGraph() const
     {
-      return m_fileDef->generateSourceFile();
+      return std::make_shared<DotInclDepGraph>(m_fileDef,FALSE);
     }
-    TemplateVariant sources() const
+    DotInclDepGraphPtr createIncludedByGraph() const
     {
-      Cachable &cache = getCache();
-      if (!cache.sources)
-      {
-        if (m_fileDef->generateSourceFile())
-        {
-          cache.sources.reset(new TemplateVariant(parseCode(m_fileDef,relPathAsString())));
-        }
-        else
-        {
-          cache.sources.reset(new TemplateVariant(""));
-        }
-      }
-      return *cache.sources;
+      return std::make_shared<DotInclDepGraph>(m_fileDef,TRUE);
     }
-    TemplateVariant version() const
+    TemplateVariant createSources() const
     {
-      return m_fileDef->fileVersion();
+      return m_fileDef->generateSourceFile() ?
+          TemplateVariant(parseCode(m_fileDef,relPathAsString())) :
+          TemplateVariant("");
     }
-    TemplateVariant classes() const
+    TemplateVariant createClasses() const
     {
-      Cachable &cache = getCache();
-      if (!cache.classes)
+      TemplateVariantList list;
+      list.reserve(m_fileDef->getClasses().size());
+      for (const auto &cd : m_fileDef->getClasses())
       {
-        TemplateList *classList = TemplateList::alloc();
-        for (const auto &cd : m_fileDef->getClasses())
+        if (cd->visibleInParentsDeclList())
         {
-          if (cd->visibleInParentsDeclList())
-          {
-            classList->append(ClassContext::alloc(cd));
-          }
+          list.push_back(ClassContext::alloc(cd));
         }
-        cache.classes.reset(classList);
       }
-      return cache.classes.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant namespaces() const
+    TemplateVariant createNamespaces() const
     {
-      Cachable &cache = getCache();
-      if (!cache.namespaces)
+      TemplateVariantList list;
+      list.reserve(m_fileDef->getNamespaces().size());
+      for (const auto &nd : m_fileDef->getNamespaces())
       {
-        TemplateList *namespaceList = TemplateList::alloc();
-        for (const auto &nd : m_fileDef->getNamespaces())
+        if (nd->isLinkable() && !nd->isConstantGroup())
         {
-          if (nd->isLinkable() && !nd->isConstantGroup())
-          {
-            namespaceList->append(NamespaceContext::alloc(nd));
-          }
+          list.push_back(NamespaceContext::alloc(nd));
         }
-        cache.namespaces.reset(namespaceList);
       }
-      return cache.namespaces.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant constantgroups() const
+    TemplateVariant createConstantgroups() const
     {
-      Cachable &cache = getCache();
-      if (!cache.constantgroups)
+      TemplateVariantList list;
+      list.reserve(m_fileDef->getNamespaces().size());
+      for (const auto &nd : m_fileDef->getNamespaces())
       {
-        TemplateList *namespaceList = TemplateList::alloc();
-        for (const auto &nd : m_fileDef->getNamespaces())
+        if (nd->isLinkable() && nd->isConstantGroup())
         {
-          if (nd->isLinkable() && nd->isConstantGroup())
-          {
-            namespaceList->append(NamespaceContext::alloc(nd));
-          }
+          list.push_back(NamespaceContext::alloc(nd));
         }
-        cache.constantgroups.reset(namespaceList);
       }
-      return cache.constantgroups.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list,
-                                  MemberListType type,const QCString &title,bool=FALSE) const
+    TemplateVariant createMemberList(MemberListType type,const QCString &title) const
     {
-      if (!list)
-      {
-        const MemberList *ml = m_fileDef->getMemberList(type);
-        if (ml)
-        {
-          list.reset(MemberListInfoContext::alloc(m_fileDef,relPathAsString(),ml,title,""));
-        }
-      }
-      if (list)
-      {
-        return list.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
+      const MemberList *ml = m_fileDef->getMemberList(type);
+      return ml ? TemplateVariant(MemberListInfoContext::alloc(m_fileDef,relPathAsString(),ml,title,""))
+                : TemplateVariant(false);
     }
-    TemplateVariant macros() const
+    TemplateVariant createMacros() const
     {
-      return getMemberList(getCache().macros,MemberListType_decDefineMembers,theTranslator->trDefines());
+      return createMemberList(MemberListType_decDefineMembers,theTranslator->trDefines());
     }
-    TemplateVariant typedefs() const
+    TemplateVariant createTypedefs() const
     {
-      return getMemberList(getCache().typedefs,MemberListType_decTypedefMembers,theTranslator->trTypedefs());
+      return createMemberList(MemberListType_decTypedefMembers,theTranslator->trTypedefs());
     }
-    TemplateVariant sequences() const
+    TemplateVariant createSequences() const
     {
-      return getMemberList(getCache().sequences,MemberListType_decSequenceMembers,theTranslator->trSequences());
+      return createMemberList(MemberListType_decSequenceMembers,theTranslator->trSequences());
     }
-    TemplateVariant dictionaries() const
+    TemplateVariant createDictionaries() const
     {
-      return getMemberList(getCache().dictionaries,MemberListType_decDictionaryMembers,theTranslator->trDictionaries());
+      return createMemberList(MemberListType_decDictionaryMembers,theTranslator->trDictionaries());
     }
-    TemplateVariant enums() const
+    TemplateVariant createEnums() const
     {
-      return getMemberList(getCache().enums,MemberListType_decEnumMembers,theTranslator->trEnumerations());
+      return createMemberList(MemberListType_decEnumMembers,theTranslator->trEnumerations());
     }
-    TemplateVariant functions() const
+    TemplateVariant createFunctions() const
     {
-      QCString title = theTranslator->trFunctions();
       SrcLangExt lang = m_fileDef->getLanguage();
-      if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprograms();
-      else if (lang==SrcLangExt_VHDL) title=theTranslator->trFunctionAndProc();
-      return getMemberList(getCache().functions,MemberListType_decFuncMembers,title);
+      return createMemberList(MemberListType_decFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprograms() :
+                                                             lang==SrcLangExt_VHDL    ? theTranslator->trFunctionAndProc() :
+                                                                                        theTranslator->trFunctions());
     }
-    TemplateVariant variables() const
+    TemplateVariant createVariables() const
     {
       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
-      return getMemberList(getCache().variables,MemberListType_decVarMembers,
-                           sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables());
+      return createMemberList(MemberListType_decVarMembers, sliceOpt ? theTranslator->trConstants() :
+                                                                       theTranslator->trVariables());
     }
-    TemplateVariant memberGroups() const
+    TemplateVariant createDetailedMacros() const
     {
-      Cachable &cache = getCache();
-      if (!cache.memberGroups)
-      {
-        if (!m_fileDef->getMemberGroups().empty())
-        {
-          cache.memberGroups.reset(MemberGroupListContext::alloc(m_fileDef,relPathAsString(),m_fileDef->getMemberGroups(),m_fileDef->subGrouping()));
-        }
-        else
-        {
-          cache.memberGroups.reset(MemberGroupListContext::alloc());
-        }
-      }
-      return cache.memberGroups.get();
+      return createMemberList(MemberListType_docDefineMembers,theTranslator->trDefineDocumentation());
     }
-    TemplateVariant detailedMacros() const
+    TemplateVariant createDetailedTypedefs() const
     {
-      return getMemberList(getCache().detailedMacros,MemberListType_docDefineMembers,theTranslator->trDefineDocumentation());
+      return createMemberList(MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
     }
-    TemplateVariant detailedTypedefs() const
+    TemplateVariant createDetailedSequences() const
     {
-      return getMemberList(getCache().detailedTypedefs,MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
+      return createMemberList(MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation());
     }
-    TemplateVariant detailedSequences() const
+    TemplateVariant createDetailedDictionaries() const
     {
-      return getMemberList(getCache().detailedSequences,MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation());
+      return createMemberList(MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation());
     }
-    TemplateVariant detailedDictionaries() const
+    TemplateVariant createDetailedEnums() const
     {
-      return getMemberList(getCache().detailedDictionaries,MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation());
+      return createMemberList(MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
     }
-    TemplateVariant detailedEnums() const
+    TemplateVariant createDetailedFunctions() const
     {
-      return getMemberList(getCache().detailedEnums,MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
+      SrcLangExt lang = m_fileDef->getLanguage();
+      return createMemberList(MemberListType_docFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprogramDocumentation() :
+                                                                                        theTranslator->trFunctionDocumentation());
     }
-    TemplateVariant detailedFunctions() const
+    TemplateVariant createDetailedVariables() const
     {
-      QCString title = theTranslator->trFunctionDocumentation();
-      SrcLangExt lang = m_fileDef->getLanguage();
-      if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprogramDocumentation();
-      return getMemberList(getCache().detailedFunctions,MemberListType_docFuncMembers,title);
+      return createMemberList(MemberListType_docVarMembers,theTranslator->trVariableDocumentation());
     }
-    TemplateVariant detailedVariables() const
+    TemplateVariant createMemberGroups() const
     {
-      return getMemberList(getCache().detailedVariables,MemberListType_docVarMembers,theTranslator->trVariableDocumentation());
+      return !m_fileDef->getMemberGroups().empty() ?
+          MemberGroupListContext::alloc(m_fileDef,relPathAsString(),m_fileDef->getMemberGroups(),m_fileDef->subGrouping()) :
+          MemberGroupListContext::alloc();
     }
-    TemplateVariant inlineClasses() const
+    TemplateVariant createInlineClasses() const
     {
-      Cachable &cache = getCache();
-      if (!cache.inlineClasses)
+      TemplateVariantList list;
+      list.reserve(m_fileDef->getClasses().size());
+      for (const auto &cd : m_fileDef->getClasses())
       {
-        TemplateList *classList = TemplateList::alloc();
-        for (const auto &cd : m_fileDef->getClasses())
+        if (!cd->isAnonymous() &&
+            cd->isLinkableInProject() &&
+            cd->isEmbeddedInOuterScope() &&
+            cd->partOfGroups().empty())
         {
-          if (!cd->isAnonymous() &&
-              cd->isLinkableInProject() &&
-              cd->isEmbeddedInOuterScope() &&
-              cd->partOfGroups().empty())
-          {
-            classList->append(ClassContext::alloc(cd));
-          }
+          list.push_back(ClassContext::alloc(cd));
         }
-        cache.inlineClasses.reset(classList);
       }
-      return cache.inlineClasses.get();
-    }
-    TemplateVariant compoundType() const
-    {
-      return theTranslator->trFile(FALSE,TRUE);
+      return TemplateImmutableList::alloc(list);
     }
 
-  private:
     const FileDef *m_fileDef;
     struct Cachable : public DefinitionContext<FileContext::Private>::Cachable
     {
-      Cachable(const FileDef *fd) : DefinitionContext<FileContext::Private>::Cachable(fd) {}
-      SharedPtr<IncludeInfoListContext>     includeInfoList;
-      std::unique_ptr<DotInclDepGraph>      includeGraph;
-      std::unique_ptr<DotInclDepGraph>      includedByGraph;
-      std::unique_ptr<TemplateVariant>      sources;
-      SharedPtr<TemplateList>               classes;
-      SharedPtr<TemplateList>               namespaces;
-      SharedPtr<TemplateList>               constantgroups;
-      SharedPtr<MemberListInfoContext>      macros;
-      SharedPtr<MemberListInfoContext>      typedefs;
-      SharedPtr<MemberListInfoContext>      sequences;
-      SharedPtr<MemberListInfoContext>      dictionaries;
-      SharedPtr<MemberListInfoContext>      enums;
-      SharedPtr<MemberListInfoContext>      functions;
-      SharedPtr<MemberListInfoContext>      variables;
-      SharedPtr<MemberGroupListContext>     memberGroups;
-      SharedPtr<MemberListInfoContext>      detailedMacros;
-      SharedPtr<MemberListInfoContext>      detailedTypedefs;
-      SharedPtr<MemberListInfoContext>      detailedSequences;
-      SharedPtr<MemberListInfoContext>      detailedDictionaries;
-      SharedPtr<MemberListInfoContext>      detailedEnums;
-      SharedPtr<MemberListInfoContext>      detailedFunctions;
-      SharedPtr<MemberListInfoContext>      detailedVariables;
-      SharedPtr<TemplateList>               inlineClasses;
+      CachedItem<TemplateVariant,    Private, &Private::createIncludeList>          includeList;
+      CachedItem<DotInclDepGraphPtr, Private, &Private::createIncludeGraph>         includeGraph;
+      CachedItem<DotInclDepGraphPtr, Private, &Private::createIncludedByGraph>      includedByGraph;
+      CachedItem<TemplateVariant,    Private, &Private::createSources>              sources;
+      CachedItem<TemplateVariant,    Private, &Private::createClasses>              classes;
+      CachedItem<TemplateVariant,    Private, &Private::createNamespaces>           namespaces;
+      CachedItem<TemplateVariant,    Private, &Private::createConstantgroups>       constantgroups;
+      CachedItem<TemplateVariant,    Private, &Private::createMacros>               macros;
+      CachedItem<TemplateVariant,    Private, &Private::createTypedefs>             typedefs;
+      CachedItem<TemplateVariant,    Private, &Private::createSequences>            sequences;
+      CachedItem<TemplateVariant,    Private, &Private::createDictionaries>         dictionaries;
+      CachedItem<TemplateVariant,    Private, &Private::createEnums>                enums;
+      CachedItem<TemplateVariant,    Private, &Private::createFunctions>            functions;
+      CachedItem<TemplateVariant,    Private, &Private::createVariables>            variables;
+      CachedItem<TemplateVariant,    Private, &Private::createMemberGroups>         memberGroups;
+      CachedItem<TemplateVariant,    Private, &Private::createDetailedMacros>       detailedMacros;
+      CachedItem<TemplateVariant,    Private, &Private::createDetailedTypedefs>     detailedTypedefs;
+      CachedItem<TemplateVariant,    Private, &Private::createDetailedSequences>    detailedSequences;
+      CachedItem<TemplateVariant,    Private, &Private::createDetailedDictionaries> detailedDictionaries;
+      CachedItem<TemplateVariant,    Private, &Private::createDetailedEnums>        detailedEnums;
+      CachedItem<TemplateVariant,    Private, &Private::createDetailedFunctions>    detailedFunctions;
+      CachedItem<TemplateVariant,    Private, &Private::createDetailedVariables>    detailedVariables;
+      CachedItem<TemplateVariant,    Private, &Private::createInlineClasses>        inlineClasses;
     };
-    Cachable &getCache() const
-    {
-      Cachable *c = static_cast<Cachable*>(m_fileDef->cookie());
-      assert(c!=0);
-      return *c;
-    }
-    static PropertyMapper<FileContext::Private> s_inst;
+    Cachable m_cachable;
+    static const PropertyMap<FileContext::Private> s_inst;
+};
+
+//%% struct File(Symbol): file information
+//%% {
+const PropertyMap<FileContext::Private> FileContext::Private::s_inst {
+  BASE_PROPERTIES,
+  {  "title",                     &Private::title },
+  {  "highlight",                 &Private::highlight },
+  {  "subhighlight",              &Private::subHighlight },
+  {  "versionInfo",               &Private::versionInfo },
+  {  "includeList",               &Private::includeList },
+  {  "hasIncludeGraph",           &Private::hasIncludeGraph },
+  {  "hasIncludedByGraph",        &Private::hasIncludedByGraph },
+  {  "includeGraph",              &Private::includeGraph },
+  {  "includedByGraph",           &Private::includedByGraph },
+  {  "hasDetails",                &Private::hasDetails },
+  {  "hasSourceFile",             &Private::hasSourceFile },
+  {  "sources",                   &Private::sources },
+  {  "version",                   &Private::version },
+  {  "classes",                   &Private::classes },
+  {  "namespaces",                &Private::namespaces },
+  {  "constantgroups",            &Private::constantgroups },
+  {  "macros",                    &Private::macros },
+  {  "typedefs",                  &Private::typedefs },
+  {  "sequences",                 &Private::sequences },
+  {  "dictionaries",              &Private::dictionaries },
+  {  "enums",                     &Private::enums },
+  {  "functions",                 &Private::functions },
+  {  "variables",                 &Private::variables },
+  {  "memberGroups",              &Private::memberGroups },
+  {  "detailedMacros",            &Private::detailedMacros },
+  {  "detailedTypedefs",          &Private::detailedTypedefs },
+  {  "detailedSequences",         &Private::detailedSequences },
+  {  "detailedDictionaries",      &Private::detailedDictionaries },
+  {  "detailedEnums",             &Private::detailedEnums },
+  {  "detailedFunctions",         &Private::detailedFunctions },
+  {  "detailedVariables",         &Private::detailedVariables },
+  {  "inlineClasses",             &Private::inlineClasses },
+  {  "compoundType",              &Private::compoundType }
 };
 //%% }
 
-PropertyMapper<FileContext::Private> FileContext::Private::s_inst;
+//PropertyMapper<FileContext::Private> FileContext::Private::s_inst;
 
-FileContext::FileContext(const FileDef *fd) : RefCountedContext("FileContext")
+FileContext::FileContext(const FileDef *fd) : p(std::make_unique<Private>(fd))
 {
-  p = new Private(fd);
 }
 
 FileContext::~FileContext()
 {
-  delete p;
 }
 
 TemplateVariant FileContext::get(const QCString &n) const
@@ -3485,105 +3112,30 @@ StringVector FileContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct Dir(Symbol): directory information
-//%% {
 class DirContext::Private : public DefinitionContext<DirContext::Private>
 {
   public:
     Private(const DirDef *dd) : DefinitionContext<DirContext::Private>(dd) , m_dirDef(dd)
     {
-      static bool init=FALSE;
-      if (!init)
-      {
-        addBaseProperties(s_inst);
-        s_inst.addProperty("title",         &Private::title);
-        s_inst.addProperty("highlight",     &Private::highlight);
-        s_inst.addProperty("subhighlight",  &Private::subHighlight);
-        s_inst.addProperty("dirName",       &Private::dirName);
-        s_inst.addProperty("dirs",          &Private::dirs);
-        s_inst.addProperty("files",         &Private::files);
-        s_inst.addProperty("hasDetails",    &Private::hasDetails);
-        s_inst.addProperty("hasDirGraph",   &Private::hasDirGraph);
-        s_inst.addProperty("dirGraph",      &Private::dirGraph);
-        s_inst.addProperty("compoundType",  &Private::compoundType);
-        init=TRUE;
-      }
-      if (!dd->cookie()) { dd->setCookie(new DirContext::Private::Cachable(dd)); }
     }
     virtual ~Private() {}
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant title() const
-    {
-      return TemplateVariant(m_dirDef->shortTitle());
-    }
-    TemplateVariant highlight() const
-    {
-      return TemplateVariant("files");
-    }
-    TemplateVariant subHighlight() const
-    {
-      return TemplateVariant("");
-    }
-    TemplateVariant dirName() const
-    {
-      return TemplateVariant(m_dirDef->shortName());
-    }
-    TemplateVariant dirs() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.dirs)
-      {
-        cache.dirs.reset(TemplateList::alloc());
-        for(const auto dd : m_dirDef->subDirs())
-        {
-          DirContext *dc = new DirContext(dd);
-          cache.dirs->append(dc);
-        }
-      }
-      return cache.dirs.get();
-    }
-    TemplateVariant files() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.files)
-      {
-        cache.files.reset(TemplateList::alloc());
-        for (const auto &fd : m_dirDef->getFiles())
-        {
-          FileContext *fc = FileContext::alloc(fd);
-          cache.files->append(fc);
-        }
-      }
-      return cache.files.get();
-    }
-    TemplateVariant hasDetails() const
-    {
-      return m_dirDef->hasDetailedDescription();
-    }
-    TemplateVariant compoundType() const
-    {
-      return theTranslator->trDir(FALSE,TRUE);
-    }
-    TemplateVariant relPath() const
-    {
-      return "";
-    }
-    DotDirDeps *getDirDepsGraph() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.dirDepsGraph)
-      {
-        cache.dirDepsGraph.reset(new DotDirDeps(m_dirDef));
-      }
-      return cache.dirDepsGraph.get();
-    }
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+    // Property getters
+    TemplateVariant title() const                { return TemplateVariant(m_dirDef->shortTitle()); }
+    TemplateVariant highlight() const            { return TemplateVariant("files"); }
+    TemplateVariant subHighlight() const         { return TemplateVariant(""); }
+    TemplateVariant dirName() const              { return TemplateVariant(m_dirDef->shortName()); }
+    TemplateVariant dirs() const                 { return m_cachable.dirs.get(this); }
+    TemplateVariant files() const                { return m_cachable.files.get(this); }
+    TemplateVariant hasDetails() const           { return m_dirDef->hasDetailedDescription(); }
+    TemplateVariant compoundType() const         { return theTranslator->trDir(FALSE,TRUE); }
+    TemplateVariant relPath() const              { return ""; }
+    DotDirDepsPtr   getDirDepsGraph() const      { return m_cachable.dirDepsGraph.get(this); }
+
     TemplateVariant hasDirGraph() const
     {
       bool result=FALSE;
@@ -3591,7 +3143,7 @@ class DirContext::Private : public DefinitionContext<DirContext::Private>
       static bool dirGraph = Config_getBool(DIRECTORY_GRAPH);
       if (haveDot && dirGraph)
       {
-        DotDirDeps *graph = getDirDepsGraph();
+        DotDirDepsPtr graph = getDirDepsGraph();
         result = !graph->isTrivial();
       }
       return result;
@@ -3603,7 +3155,7 @@ class DirContext::Private : public DefinitionContext<DirContext::Private>
       static bool dirGraph = Config_getBool(DIRECTORY_GRAPH);
       if (haveDot && dirGraph)
       {
-        DotDirDeps *graph = getDirDepsGraph();
+        DotDirDepsPtr graph = getDirDepsGraph();
         switch (g_globals.outputFormat)
         {
           case ContextOutputFormat_Html:
@@ -3611,7 +3163,7 @@ class DirContext::Private : public DefinitionContext<DirContext::Private>
               graph->writeGraph(t,GOF_BITMAP,
                                 EOF_Html,
                                 g_globals.outputDir,
-                                g_globals.outputDir+Portable::pathSeparator()+m_dirDef->getOutputFileBase()+Doxygen::htmlFileExtension,
+                                g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_dirDef->getOutputFileBase()),
                                 relPathAsString(),
                                 TRUE,
                                 g_globals.dynSectionId,
@@ -3641,34 +3193,66 @@ class DirContext::Private : public DefinitionContext<DirContext::Private>
     }
 
   private:
+    TemplateVariant createDirs() const
+    {
+      TemplateVariantList list;
+      list.reserve(m_dirDef->subDirs().size());
+      for(const auto dd : m_dirDef->subDirs())
+      {
+        list.push_back(DirContext::alloc(dd));
+      }
+      return TemplateImmutableList::alloc(list);
+    }
+    TemplateVariant createFiles() const
+    {
+      TemplateVariantList list;
+      list.reserve(m_dirDef->getFiles().size());
+      for (const auto &fd : m_dirDef->getFiles())
+      {
+        list.push_back(FileContext::alloc(fd));
+      }
+      return TemplateImmutableList::alloc(list);
+    }
+    DotDirDepsPtr createDirDepsGraph() const
+    {
+      return std::make_shared<DotDirDeps>(m_dirDef);
+    }
     const DirDef *m_dirDef;
     struct Cachable : public DefinitionContext<DirContext::Private>::Cachable
     {
-      Cachable(const DirDef *dd) : DefinitionContext<DirContext::Private>::Cachable(dd) {}
-      SharedPtr<TemplateList>  dirs;
-      SharedPtr<TemplateList>  files;
-      std::unique_ptr<DotDirDeps>    dirDepsGraph;
+      CachedItem<TemplateVariant,  Private, &Private::createDirs>         dirs;
+      CachedItem<TemplateVariant,  Private, &Private::createFiles>        files;
+      CachedItem<DotDirDepsPtr,    Private, &Private::createDirDepsGraph> dirDepsGraph;
     };
-    Cachable &getCache() const
-    {
-      Cachable *c = static_cast<Cachable*>(m_dirDef->cookie());
-      assert(c!=0);
-      return *c;
-    }
-    static PropertyMapper<DirContext::Private> s_inst;
+    Cachable m_cachable;
+    static const PropertyMap<DirContext::Private> s_inst;
+};
+
+//%% struct Dir(Symbol): directory information
+//%% {
+const PropertyMap<DirContext::Private> DirContext::Private::s_inst {
+  BASE_PROPERTIES,
+  {  "title",         &Private::title },
+  {  "highlight",     &Private::highlight },
+  {  "subhighlight",  &Private::subHighlight },
+  {  "dirName",       &Private::dirName },
+  {  "dirs",          &Private::dirs },
+  {  "files",         &Private::files },
+  {  "hasDetails",    &Private::hasDetails },
+  {  "hasDirGraph",   &Private::hasDirGraph },
+  {  "dirGraph",      &Private::dirGraph },
+  {  "compoundType",  &Private::compoundType }
 };
 //%% }
 
-PropertyMapper<DirContext::Private> DirContext::Private::s_inst;
+//PropertyMapper<DirContext::Private> DirContext::Private::s_inst;
 
-DirContext::DirContext(const DirDef *fd) : RefCountedContext("DirContext")
+DirContext::DirContext(const DirDef *fd) : p(std::make_unique<Private>(fd))
 {
-  p = new Private(fd);
 }
 
 DirContext::~DirContext()
 {
-  delete p;
 }
 
 TemplateVariant DirContext::get(const QCString &n) const
@@ -3683,8 +3267,6 @@ StringVector DirContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct Page(Symbol): page information
-//%% {
 class PageContext::Private : public DefinitionContext<PageContext::Private>
 {
   public:
@@ -3692,27 +3274,14 @@ class PageContext::Private : public DefinitionContext<PageContext::Private>
       : DefinitionContext<PageContext::Private>(pd) , m_pageDef(pd), m_isMainPage(isMainPage),
         m_isExample(isExample)
     {
-      static bool init=FALSE;
-      if (!init)
-      {
-        addBaseProperties(s_inst);
-        s_inst.addProperty("title",       &Private::title);
-        s_inst.addProperty("highlight",   &Private::highlight);
-        s_inst.addProperty("subhighlight",&Private::subHighlight);
-        s_inst.addProperty("example",     &Private::example);
-        init=TRUE;
-      }
-      if (!pd->cookie()) { pd->setCookie(new PageContext::Private::Cachable(pd)); }
     }
     virtual ~Private() {}
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+    // Property getters
     TemplateVariant title() const
     {
       if (m_isMainPage)
@@ -3749,14 +3318,8 @@ class PageContext::Private : public DefinitionContext<PageContext::Private>
     }
     TemplateVariant relPath() const
     {
-      if (m_isMainPage)
-      {
-        return "";
-      }
-      else
-      {
-        return DefinitionContext<PageContext::Private>::relPath();
-      }
+      return m_isMainPage ? TemplateVariant("") :
+                            TemplateVariant(DefinitionContext<PageContext::Private>::relPath());
     }
     TemplateVariant highlight() const
     {
@@ -3775,54 +3338,45 @@ class PageContext::Private : public DefinitionContext<PageContext::Private>
     }
     TemplateVariant example() const
     {
-      if (m_isExample)
-      {
-        Cachable &cache = getCache();
-        if (!cache.example || g_globals.outputFormat!=cache.exampleOutputFormat)
-        {
-          cache.example.reset(new TemplateVariant(
-                parseDoc(m_pageDef,m_pageDef->docFile(),m_pageDef->docLine(),
-                  relPathAsString(),"\\include "+m_pageDef->name(),FALSE)));
-          cache.exampleOutputFormat = g_globals.outputFormat;
-        }
-        return *cache.example;
-      }
-      else
-      {
-        return TemplateVariant("");
-      }
+      return m_cachable.example.get(this);
     }
   private:
+    TemplateVariant createExample() const
+    {
+      return m_isExample ?
+          TemplateVariant(parseDoc(m_pageDef,m_pageDef->docFile(),m_pageDef->docLine(),
+                  relPathAsString(),"\\include "+m_pageDef->name(),FALSE)) :
+          TemplateVariant("");
+    }
+
     const PageDef *m_pageDef;
     struct Cachable : public DefinitionContext<PageContext::Private>::Cachable
     {
-      Cachable(const PageDef *pd) : DefinitionContext<PageContext::Private>::Cachable(pd),
-                              exampleOutputFormat(ContextOutputFormat_Unspecified) { }
-      std::unique_ptr<TemplateVariant> example;
-      ContextOutputFormat        exampleOutputFormat;
+      CachedItem<TemplateVariant,  Private, &Private::createExample> example;
     };
-    Cachable &getCache() const
-    {
-      Cachable *c = static_cast<Cachable*>(m_pageDef->cookie());
-      assert(c!=0);
-      return *c;
-    }
+    Cachable m_cachable;
     bool m_isMainPage;
     bool m_isExample;
-    static PropertyMapper<PageContext::Private> s_inst;
+    static const PropertyMap<PageContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<PageContext::Private> PageContext::Private::s_inst;
+//%% struct Page(Symbol): page information
+//%% {
+const PropertyMap<PageContext::Private> PageContext::Private::s_inst {
+  BASE_PROPERTIES,
+  {  "title",       &Private::title },
+  {  "highlight",   &Private::highlight },
+  {  "subhighlight",&Private::subHighlight },
+  {  "example",     &Private::example }
+};
+//%% }
 
-PageContext::PageContext(const PageDef *pd,bool isMainPage,bool isExample) : RefCountedContext("PageContext")
+PageContext::PageContext(const PageDef *pd,bool isMainPage,bool isExample) : p(std::make_unique<Private>(pd,isMainPage,isExample))
 {
-  p = new Private(pd,isMainPage,isExample);
 }
 
 PageContext::~PageContext()
 {
-  delete p;
 }
 
 TemplateVariant PageContext::get(const QCString &n) const
@@ -3906,7 +3460,7 @@ class TextGeneratorHtml : public TextGeneratorIntf
       }
       m_ts << "href=\"";
       m_ts << externalRef(m_relPath,ref,TRUE);
-      if (!f.isEmpty()) m_ts << f << Doxygen::htmlFileExtension;
+      if (!f.isEmpty()) m_ts << addHtmlExtensionIfMissing(f);
       if (!anchor.isEmpty()) m_ts << "#" << anchor;
       m_ts << "\">";
       m_ts << convertToHtml(name);
@@ -3983,8 +3537,7 @@ class TextGeneratorFactory
   public:
     static TextGeneratorFactory *instance()
     {
-      static TextGeneratorFactory *instance = 0;
-      if (instance==0) instance = new TextGeneratorFactory;
+      static TextGeneratorFactory *instance = new TextGeneratorFactory;
       return instance;
     }
     TextGeneratorIntf *create(TextStream &ts,const QCString &relPath)
@@ -4021,748 +3574,427 @@ TemplateVariant createLinkedText(const Definition *def,const QCString &relPath,c
   }
 }
 
-//%% struct Member(Symbol): member information
-//%% {
 class MemberContext::Private : public DefinitionContext<MemberContext::Private>
 {
   public:
     Private(const MemberDef *md) : DefinitionContext<MemberContext::Private>(md) , m_memberDef(md)
     {
-      static bool init=FALSE;
-      if (!init)
-      {
-        addBaseProperties(s_inst);
-        s_inst.addProperty("isSignal",            &Private::isSignal);
-        s_inst.addProperty("isSlot",              &Private::isSlot);
-        s_inst.addProperty("isVariable",          &Private::isVariable);
-        s_inst.addProperty("isEnumeration",       &Private::isEnumeration);
-        s_inst.addProperty("isEnumValue",         &Private::isEnumValue);
-        s_inst.addProperty("isTypedef",           &Private::isTypedef);
-        s_inst.addProperty("isFunction",          &Private::isFunction);
-        s_inst.addProperty("isFunctionPtr",       &Private::isFunctionPtr);
-        s_inst.addProperty("isDefine",            &Private::isDefine);
-        s_inst.addProperty("isFriend",            &Private::isFriend);
-        s_inst.addProperty("isProperty",          &Private::isProperty);
-        s_inst.addProperty("isEvent",             &Private::isEvent);
-        s_inst.addProperty("isRelated",           &Private::isRelated);
-        s_inst.addProperty("isForeign",           &Private::isForeign);
-        s_inst.addProperty("isStatic",            &Private::isStatic);
-        s_inst.addProperty("isInline",            &Private::isInline);
-        s_inst.addProperty("isExplicit",          &Private::isExplicit);
-        s_inst.addProperty("isMutable",           &Private::isMutable);
-        s_inst.addProperty("isGettable",          &Private::isGettable);
-        s_inst.addProperty("isPrivateGettable",   &Private::isPrivateGettable);
-        s_inst.addProperty("isProtectedGettable", &Private::isProtectedGettable);
-        s_inst.addProperty("isSettable",          &Private::isSettable);
-        s_inst.addProperty("isPrivateSettable",   &Private::isPrivateSettable);
-        s_inst.addProperty("isProtectedSettable", &Private::isProtectedSettable);
-        s_inst.addProperty("isReadable",          &Private::isReadable);
-        s_inst.addProperty("isWritable",          &Private::isWritable);
-        s_inst.addProperty("isAddable",           &Private::isAddable);
-        s_inst.addProperty("isRemovable",         &Private::isRemovable);
-        s_inst.addProperty("isRaisable",          &Private::isRaisable);
-        s_inst.addProperty("isFinal",             &Private::isFinal);
-        s_inst.addProperty("isAbstract",          &Private::isAbstract);
-        s_inst.addProperty("isOverride",          &Private::isOverride);
-        s_inst.addProperty("isInitonly",          &Private::isInitonly);
-        s_inst.addProperty("isOptional",          &Private::isOptional);
-        s_inst.addProperty("isRequired",          &Private::isRequired);
-        s_inst.addProperty("isNonAtomic",         &Private::isNonAtomic);
-        s_inst.addProperty("isCopy",              &Private::isCopy);
-        s_inst.addProperty("isAssign",            &Private::isAssign);
-        s_inst.addProperty("isRetain",            &Private::isRetain);
-        s_inst.addProperty("isWeak",              &Private::isWeak);
-        s_inst.addProperty("isStrong",            &Private::isStrong);
-        s_inst.addProperty("isEnumStruct",        &Private::isEnumStruct);
-        s_inst.addProperty("isUnretained",        &Private::isUnretained);
-        s_inst.addProperty("isNew",               &Private::isNew);
-        s_inst.addProperty("isSealed",            &Private::isSealed);
-        s_inst.addProperty("isImplementation",    &Private::isImplementation);
-        s_inst.addProperty("isExternal",          &Private::isExternal);
-        s_inst.addProperty("isTypeAlias",         &Private::isTypeAlias);
-        s_inst.addProperty("isDefault",           &Private::isDefault);
-        s_inst.addProperty("isDelete",            &Private::isDelete);
-        s_inst.addProperty("isNoExcept",          &Private::isNoExcept);
-        s_inst.addProperty("isAttribute",         &Private::isAttribute);
-        s_inst.addProperty("isUNOProperty",       &Private::isUNOProperty);
-        s_inst.addProperty("isReadonly",          &Private::isReadonly);
-        s_inst.addProperty("isBound",             &Private::isBound);
-        s_inst.addProperty("isConstrained",       &Private::isConstrained);
-        s_inst.addProperty("isTransient",         &Private::isTransient);
-        s_inst.addProperty("isMaybeVoid",         &Private::isMaybeVoid);
-        s_inst.addProperty("isMaybeDefault",      &Private::isMaybeDefault);
-        s_inst.addProperty("isMaybeAmbiguous",    &Private::isMaybeAmbiguous);
-        s_inst.addProperty("isPublished",         &Private::isPublished);
-        s_inst.addProperty("isTemplateSpecialization",&Private::isTemplateSpecialization);
-        s_inst.addProperty("isObjCMethod",        &Private::isObjCMethod);
-        s_inst.addProperty("isObjCProperty",      &Private::isObjCProperty);
-        s_inst.addProperty("isAnonymous",         &Private::isAnonymous);
-        s_inst.addProperty("hasParameters",       &Private::hasParameters);
-        s_inst.addProperty("declType",            &Private::declType);
-        s_inst.addProperty("declArgs",            &Private::declArgs);
-        s_inst.addProperty("anonymousType",       &Private::anonymousType);
-        s_inst.addProperty("anonymousMember",     &Private::anonymousMember);
-        s_inst.addProperty("hasDetails",          &Private::hasDetails);
-        s_inst.addProperty("exception",           &Private::exception);
-        s_inst.addProperty("bitfields",           &Private::bitfields);
-        s_inst.addProperty("initializer",         &Private::initializer);
-        s_inst.addProperty("initializerAsCode",   &Private::initializerAsCode);
-        s_inst.addProperty("hasOneLineInitializer",   &Private::hasOneLineInitializer);
-        s_inst.addProperty("hasMultiLineInitializer", &Private::hasMultiLineInitializer);
-        s_inst.addProperty("templateArgs",        &Private::templateArgs);
-        s_inst.addProperty("templateAlias",       &Private::templateAlias);
-        s_inst.addProperty("propertyAttrs",       &Private::propertyAttrs);
-        s_inst.addProperty("eventAttrs",          &Private::eventAttrs);
-        s_inst.addProperty("category",            &Private::category);
-        s_inst.addProperty("categoryRelation",    &Private::categoryRelation);
-        s_inst.addProperty("class",               &Private::getClass);
-        s_inst.addProperty("file",                &Private::getFile);
-        s_inst.addProperty("namespace",           &Private::getNamespace);
-        s_inst.addProperty("definition",          &Private::definition);
-        s_inst.addProperty("parameters",          &Private::parameters);
-        s_inst.addProperty("hasConstQualifier",   &Private::hasConstQualifier);
-        s_inst.addProperty("hasVolatileQualifier",&Private::hasVolatileQualifier);
-        s_inst.addProperty("hasRefQualifierLValue", &Private::hasRefQualifierLValue);
-        s_inst.addProperty("hasRefQualifierRValue", &Private::hasRefQualifierRValue);
-        s_inst.addProperty("trailingReturnType",  &Private::trailingReturnType);
-        s_inst.addProperty("extraTypeChars",      &Private::extraTypeChars);
-        s_inst.addProperty("templateDecls",       &Private::templateDecls);
-        s_inst.addProperty("labels",              &Private::labels);
-        s_inst.addProperty("enumBaseType",        &Private::enumBaseType);
-        s_inst.addProperty("enumValues",          &Private::enumValues);
-        s_inst.addProperty("paramDocs",           &Private::paramDocs);
-        s_inst.addProperty("reimplements",        &Private::reimplements);
-        s_inst.addProperty("implements",          &Private::implements);
-        s_inst.addProperty("reimplementedBy",     &Private::reimplementedBy);
-        s_inst.addProperty("implementedBy",       &Private::implementedBy);
-        s_inst.addProperty("examples",            &Private::examples);
-        s_inst.addProperty("typeConstraints",     &Private::typeConstraints);
-        s_inst.addProperty("functionQualifier",   &Private::functionQualifier);
-        s_inst.addProperty("sourceRefs",          &Private::sourceRefs);
-        s_inst.addProperty("sourceRefBys",        &Private::sourceRefBys);
-        s_inst.addProperty("hasSources",          &Private::hasSources);
-        s_inst.addProperty("sourceCode",          &Private::sourceCode);
-        s_inst.addProperty("hasCallGraph",        &Private::hasCallGraph);
-        s_inst.addProperty("callGraph",           &Private::callGraph);
-        s_inst.addProperty("hasCallerGraph",      &Private::hasCallerGraph);
-        s_inst.addProperty("callerGraph",         &Private::callerGraph);
-        s_inst.addProperty("hasReferencedByRelation", &Private::hasReferencedByRelation);
-        s_inst.addProperty("referencedByRelation",    &Private::referencedByRelation);
-        s_inst.addProperty("hasReferencesRelation",   &Private::hasReferencesRelation);
-        s_inst.addProperty("referencesRelation",      &Private::referencesRelation);
-        s_inst.addProperty("fieldType",           &Private::fieldType);
-        s_inst.addProperty("type",                &Private::type);
-        s_inst.addProperty("detailsVisibleFor",   &Private::detailsVisibleFor);
-        s_inst.addProperty("nameWithContextFor",  &Private::nameWithContextFor);
-        init=TRUE;
-      }
-      if (!md->cookie()) { md->setCookie(new MemberContext::Private::Cachable(md)); }
-
-      Cachable &cache = getCache();
-      cache.propertyAttrs.reset(TemplateList::alloc());
-      if (md->isProperty())
-      {
-        if (md->isGettable())           cache.propertyAttrs->append("get");
-        if (md->isPrivateGettable())    cache.propertyAttrs->append("private get");
-        if (md->isProtectedGettable())  cache.propertyAttrs->append("protected get");
-        if (md->isSettable())           cache.propertyAttrs->append("set");
-        if (md->isPrivateSettable())    cache.propertyAttrs->append("private set");
-        if (md->isProtectedSettable())  cache.propertyAttrs->append("protected set");
-      }
-      cache.eventAttrs.reset(TemplateList::alloc());
-      if (md->isEvent())
-      {
-        if (md->isAddable())   cache.eventAttrs->append("add");
-        if (md->isRemovable()) cache.eventAttrs->append("remove");
-        if (md->isRaisable())  cache.eventAttrs->append("raise");
-      }
     }
     virtual ~Private() {}
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant fieldType() const
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+    // Property getters
+    TemplateVariant isStatic() const                 { return m_memberDef->isStatic(); }
+    TemplateVariant isObjCMethod() const             { return m_memberDef->isObjCMethod(); }
+    TemplateVariant isObjCProperty() const           { return m_memberDef->isObjCProperty(); }
+    TemplateVariant isCSharpProperty() const         { return m_memberDef->isCSharpProperty(); }
+    TemplateVariant isImplementation() const         { return m_memberDef->isImplementation(); }
+    TemplateVariant isSignal() const                 { return m_memberDef->isSignal(); }
+    TemplateVariant isSlot() const                   { return m_memberDef->isSlot(); }
+    TemplateVariant isTypedef() const                { return m_memberDef->isTypedef(); }
+    TemplateVariant isFunction() const               { return m_memberDef->isFunction(); }
+    TemplateVariant isFunctionPtr() const            { return m_memberDef->isFunctionPtr(); }
+    TemplateVariant isFriend() const                 { return m_memberDef->isFriend(); }
+    TemplateVariant isForeign() const                { return m_memberDef->isForeign(); }
+    TemplateVariant isEvent() const                  { return m_memberDef->isEvent(); }
+    TemplateVariant isInline() const                 { return m_memberDef->isInline(); }
+    TemplateVariant isExplicit() const               { return m_memberDef->isExplicit(); }
+    TemplateVariant isMutable() const                { return m_memberDef->isMutable(); }
+    TemplateVariant isGettable() const               { return m_memberDef->isGettable(); }
+    TemplateVariant isPrivateGettable() const        { return m_memberDef->isPrivateGettable(); }
+    TemplateVariant isProtectedGettable() const      { return m_memberDef->isProtectedGettable(); }
+    TemplateVariant isSettable() const               { return m_memberDef->isSettable(); }
+    TemplateVariant isPrivateSettable() const        { return m_memberDef->isPrivateSettable(); }
+    TemplateVariant isProtectedSettable() const      { return m_memberDef->isProtectedSettable(); }
+    TemplateVariant isReadable() const               { return m_memberDef->isReadable(); }
+    TemplateVariant isWritable() const               { return m_memberDef->isWritable(); }
+    TemplateVariant isAddable() const                { return m_memberDef->isAddable(); }
+    TemplateVariant isRemovable() const              { return m_memberDef->isRemovable(); }
+    TemplateVariant isRaisable() const               { return m_memberDef->isRaisable(); }
+    TemplateVariant isFinal() const                  { return m_memberDef->isFinal(); }
+    TemplateVariant isAbstract() const               { return m_memberDef->isAbstract(); }
+    TemplateVariant isOverride() const               { return m_memberDef->isOverride(); }
+    TemplateVariant isInitonly() const               { return m_memberDef->isInitonly(); }
+    TemplateVariant isOptional() const               { return m_memberDef->isOptional(); }
+    TemplateVariant isRequired() const               { return m_memberDef->isRequired(); }
+    TemplateVariant isNonAtomic() const              { return m_memberDef->isNonAtomic(); }
+    TemplateVariant isCopy() const                   { return m_memberDef->isCopy(); }
+    TemplateVariant isAssign() const                 { return m_memberDef->isAssign(); }
+    TemplateVariant isRetain() const                 { return m_memberDef->isRetain(); }
+    TemplateVariant isWeak() const                   { return m_memberDef->isWeak(); }
+    TemplateVariant isStrong() const                 { return m_memberDef->isStrong(); }
+    TemplateVariant isEnumStruct() const             { return m_memberDef->isEnumStruct(); }
+    TemplateVariant isUnretained() const             { return m_memberDef->isUnretained(); }
+    TemplateVariant isNew() const                    { return m_memberDef->isNew(); }
+    TemplateVariant isSealed() const                 { return m_memberDef->isSealed(); }
+    TemplateVariant isExternal() const               { return m_memberDef->isExternal(); }
+    TemplateVariant isTypeAlias() const              { return m_memberDef->isTypeAlias(); }
+    TemplateVariant isDefault() const                { return m_memberDef->isDefault(); }
+    TemplateVariant isDelete() const                 { return m_memberDef->isDelete(); }
+    TemplateVariant isNoExcept() const               { return m_memberDef->isNoExcept(); }
+    TemplateVariant isAttribute() const              { return m_memberDef->isAttribute(); }
+    TemplateVariant isUNOProperty() const            { return m_memberDef->isUNOProperty(); }
+    TemplateVariant isReadonly() const               { return m_memberDef->isReadonly(); }
+    TemplateVariant isBound() const                  { return m_memberDef->isBound(); }
+    TemplateVariant isConstrained() const            { return m_memberDef->isConstrained(); }
+    TemplateVariant isTransient() const              { return m_memberDef->isTransient(); }
+    TemplateVariant isMaybeVoid() const              { return m_memberDef->isMaybeVoid(); }
+    TemplateVariant isMaybeDefault() const           { return m_memberDef->isMaybeDefault(); }
+    TemplateVariant isMaybeAmbiguous() const         { return m_memberDef->isMaybeAmbiguous(); }
+    TemplateVariant isPublished() const              { return m_memberDef->isPublished(); }
+    TemplateVariant isTemplateSpecialization() const { return m_memberDef->isTemplateSpecialization(); }
+    TemplateVariant isProperty() const               { return m_memberDef->isProperty(); }
+    TemplateVariant isEnumValue() const              { return m_memberDef->isEnumValue(); }
+    TemplateVariant isVariable() const               { return m_memberDef->isVariable(); }
+    TemplateVariant isEnumeration() const            { return m_memberDef->isEnumerate(); }
+    TemplateVariant hasDetails() const               { return m_memberDef->hasDetailedDescription(); }
+    TemplateVariant isDefine() const                 { return m_memberDef->isDefine(); }
+    TemplateVariant isAnonymous() const              { return m_memberDef->isAnonymous(); }
+    TemplateVariant isRelated() const                { return m_memberDef->isRelated(); }
+    TemplateVariant enumBaseType() const             { return m_memberDef->enumBaseType(); }
+    TemplateVariant hasOneLineInitializer() const    { return m_memberDef->hasOneLineInitializer(); }
+    TemplateVariant hasMultiLineInitializer() const  { return m_memberDef->hasMultiLineInitializer(); }
+    TemplateVariant extraTypeChars() const           { return m_memberDef->extraTypeChars(); }
+    TemplateVariant type() const                     { return m_memberDef->typeString(); }
+    TemplateVariant fieldType() const                { return m_cachable.fieldType.get(this); }
+    TemplateVariant declType() const                 { return m_cachable.declType.get(this); }
+    TemplateVariant declArgs() const                 { return m_cachable.declArgs.get(this); }
+    TemplateVariant exception() const                { return m_cachable.exception.get(this); }
+    TemplateVariant bitfields() const                { return m_cachable.bitfields.get(this); }
+    TemplateVariant initializer() const              { return m_cachable.initializer.get(this); }
+    TemplateVariant initializerAsCode() const        { return m_cachable.initializerAsCode.get(this); }
+    TemplateVariant anonymousType() const            { return m_cachable.anonymousType.get(this); }
+    TemplateVariant anonymousMember() const          { return m_cachable.anonymousMember.get(this); }
+    TemplateVariant enumValues() const               { return m_cachable.enumValues.get(this); }
+    TemplateVariant templateArgs() const             { return m_cachable.templateArgs.get(this); }
+    TemplateVariant templateAlias() const            { return m_cachable.templateAlias.get(this); }
+    TemplateVariant propertyAttrs() const            { return m_cachable.propertyAttrs.get(this); }
+    TemplateVariant eventAttrs() const               { return m_cachable.eventAttrs.get(this); }
+    TemplateVariant getClass() const                 { return m_cachable.classDef.get(this); }
+    TemplateVariant category() const                 { return m_cachable.category.get(this); }
+    TemplateVariant categoryRelation() const         { return m_cachable.categoryRelation.get(this); }
+    TemplateVariant getFile() const                  { return m_cachable.fileDef.get(this); }
+    TemplateVariant getNamespace() const             { return m_cachable.namespaceDef.get(this); }
+    TemplateVariant definition() const               { return m_cachable.definition.get(this); }
+    TemplateVariant parameters() const               { return m_cachable.parameters.get(this); }
+    TemplateVariant hasParameters() const            { return !getDefArgList().empty(); }
+    TemplateVariant hasConstQualifier() const        { return getDefArgList().constSpecifier(); }
+    TemplateVariant hasVolatileQualifier() const     { return getDefArgList().volatileSpecifier(); }
+    TemplateVariant hasRefQualifierLValue() const    { return getDefArgList().refQualifier()==RefQualifierLValue; }
+    TemplateVariant hasRefQualifierRValue() const    { return getDefArgList().refQualifier()==RefQualifierRValue; }
+    TemplateVariant trailingReturnType() const       { return m_cachable.trailingReturnType.get(this); }
+    TemplateVariant templateDecls() const            { return m_cachable.templateDecls.get(this); }
+    TemplateVariant labels() const                   { return m_cachable.labels.get(this); }
+    TemplateVariant paramDocs() const                { return m_cachable.paramDocs.get(this); }
+    TemplateVariant implements() const               { return m_cachable.implements.get(this); }
+    TemplateVariant reimplements() const             { return m_cachable.reimplements.get(this); }
+    TemplateVariant implementedBy() const            { return m_cachable.implementedBy.get(this); }
+    TemplateVariant reimplementedBy() const          { return m_cachable.reimplementedBy.get(this); }
+    TemplateVariant examples() const                 { return m_cachable.examples.get(this); }
+    TemplateVariant typeConstraints() const          { return m_cachable.typeConstraints.get(this); }
+    TemplateVariant sourceRefs() const               { return m_cachable.sourceRefs.get(this); }
+    TemplateVariant sourceRefBys() const             { return m_cachable.sourceRefBys.get(this); }
+    TemplateVariant sourceCode() const               { return m_cachable.sourceCode.get(this); }
+    DotCallGraphPtr getCallGraph() const             { return m_cachable.callGraph.get(this); }
+    DotCallGraphPtr getCallerGraph() const           { return m_cachable.callerGraph.get(this); }
+    TemplateVariant hasSources() const               { return TemplateVariant(m_memberDef->hasSources()); }
+    TemplateVariant hasReferencedByRelation() const  { return TemplateVariant(m_memberDef->hasReferencedByRelation()); }
+    TemplateVariant hasReferencesRelation() const    { return TemplateVariant(m_memberDef->hasReferencesRelation()); }
+
+    const ArgumentList &getDefArgList() const
     {
-      return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->fieldType());
+      return (m_memberDef->isDocsForDefinition()) ?
+              m_memberDef->argumentList() : m_memberDef->declArgumentList();
     }
-    TemplateVariant declType() const
+
+    TemplateVariant functionQualifier() const
     {
-      Cachable &cache = getCache();
-      if (!cache.declTypeParsed)
+      if (!m_memberDef->isObjCMethod() &&
+          (m_memberDef->isFunction()  || m_memberDef->isSlot() ||
+           m_memberDef->isPrototype() || m_memberDef->isSignal()
+          )
+         )
       {
-        cache.declType=createLinkedText(m_memberDef,relPathAsString(),m_memberDef->getDeclType());
-        cache.declTypeParsed = TRUE;
-        return cache.declType;
+        return "()";
       }
       else
       {
-        return cache.declType;
+        return "";
       }
     }
-    TemplateVariant declArgs() const
+    TemplateVariant hasCallGraph() const
     {
-      Cachable &cache = getCache();
-      if (!cache.declArgsParsed)
-      {
-        cache.declArgs=createLinkedText(m_memberDef,relPathAsString(),m_memberDef->argsString());
-        cache.declArgsParsed = TRUE;
-        return cache.declArgs;
-      }
-      else
+      static bool haveDot = Config_getBool(HAVE_DOT);
+      if (m_memberDef->hasCallGraph() && haveDot &&
+          (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal()))
       {
-        return cache.declArgs;
+        DotCallGraphPtr cg = getCallGraph();
+        return !cg->isTooBig() && !cg->isTrivial();
       }
+      return TemplateVariant(FALSE);
     }
-    TemplateVariant exception() const
-    {
-      return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->excpString());
-    }
-    TemplateVariant bitfields() const
-    {
-      return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->bitfieldString());
-    }
-    TemplateVariant isStatic() const
-    {
-      return m_memberDef->isStatic();
-    }
-    TemplateVariant isObjCMethod() const
-    {
-      return m_memberDef->isObjCMethod();
-    }
-    TemplateVariant isObjCProperty() const
-    {
-      return m_memberDef->isObjCProperty();
-    }
-    TemplateVariant isImplementation() const
+    TemplateVariant callGraph() const
     {
-      return m_memberDef->isImplementation();
-    }
-    TemplateVariant isSignal() const
-    {
-      return m_memberDef->isSignal();
-    }
-    TemplateVariant isSlot() const
-    {
-      return m_memberDef->isSlot();
-    }
-    TemplateVariant isTypedef() const
-    {
-      return m_memberDef->isTypedef();
-    }
-    TemplateVariant isFunction() const
-    {
-      return m_memberDef->isFunction();
-    }
-    TemplateVariant isFunctionPtr() const
-    {
-      return m_memberDef->isFunctionPtr();
-    }
-    TemplateVariant isFriend() const
-    {
-      return m_memberDef->isFriend();
-    }
-    TemplateVariant isForeign() const
-    {
-      return m_memberDef->isForeign();
-    }
-    TemplateVariant isEvent() const
-    {
-      return m_memberDef->isEvent();
-    }
-    TemplateVariant isInline() const
-    {
-      return m_memberDef->isInline();
-    }
-    TemplateVariant isExplicit() const
-    {
-      return m_memberDef->isExplicit();
-    }
-    TemplateVariant isMutable() const
-    {
-      return m_memberDef->isMutable();
-    }
-    TemplateVariant isGettable() const
-    {
-      return m_memberDef->isGettable();
-    }
-    TemplateVariant isPrivateGettable() const
-    {
-      return m_memberDef->isPrivateGettable();
-    }
-    TemplateVariant isProtectedGettable() const
-    {
-      return m_memberDef->isProtectedGettable();
-    }
-    TemplateVariant isSettable() const
-    {
-      return m_memberDef->isSettable();
-    }
-    TemplateVariant isPrivateSettable() const
-    {
-      return m_memberDef->isPrivateSettable();
-    }
-    TemplateVariant isProtectedSettable() const
-    {
-      return m_memberDef->isProtectedSettable();
-    }
-    TemplateVariant isReadable() const
-    {
-      return m_memberDef->isReadable();
-    }
-    TemplateVariant isWritable() const
-    {
-      return m_memberDef->isWritable();
-    }
-    TemplateVariant isAddable() const
-    {
-      return m_memberDef->isAddable();
-    }
-    TemplateVariant isRemovable() const
-    {
-      return m_memberDef->isRemovable();
-    }
-    TemplateVariant isRaisable() const
-    {
-      return m_memberDef->isRaisable();
-    }
-    TemplateVariant isFinal() const
-    {
-      return m_memberDef->isFinal();
-    }
-    TemplateVariant isAbstract() const
-    {
-      return m_memberDef->isAbstract();
-    }
-    TemplateVariant isOverride() const
-    {
-      return m_memberDef->isOverride();
-    }
-    TemplateVariant isInitonly() const
-    {
-      return m_memberDef->isInitonly();
-    }
-    TemplateVariant isOptional() const
-    {
-      return m_memberDef->isOptional();
-    }
-    TemplateVariant isRequired() const
-    {
-      return m_memberDef->isRequired();
-    }
-    TemplateVariant isNonAtomic() const
-    {
-      return m_memberDef->isNonAtomic();
-    }
-    TemplateVariant isCopy() const
-    {
-      return m_memberDef->isCopy();
-    }
-    TemplateVariant isAssign() const
-    {
-      return m_memberDef->isAssign();
-    }
-    TemplateVariant isRetain() const
-    {
-      return m_memberDef->isRetain();
-    }
-    TemplateVariant isWeak() const
-    {
-      return m_memberDef->isWeak();
-    }
-    TemplateVariant isStrong() const
-    {
-      return m_memberDef->isStrong();
-    }
-    TemplateVariant isEnumStruct() const
-    {
-      return m_memberDef->isEnumStruct();
-    }
-    TemplateVariant isUnretained() const
-    {
-      return m_memberDef->isUnretained();
-    }
-    TemplateVariant isNew() const
-    {
-      return m_memberDef->isNew();
-    }
-    TemplateVariant isSealed() const
-    {
-      return m_memberDef->isSealed();
-    }
-    TemplateVariant isExternal() const
-    {
-      return m_memberDef->isExternal();
-    }
-    TemplateVariant isTypeAlias() const
-    {
-      return m_memberDef->isTypeAlias();
-    }
-    TemplateVariant isDefault() const
-    {
-      return m_memberDef->isDefault();
-    }
-    TemplateVariant isDelete() const
-    {
-      return m_memberDef->isDelete();
-    }
-    TemplateVariant isNoExcept() const
-    {
-      return m_memberDef->isNoExcept();
-    }
-    TemplateVariant isAttribute() const
-    {
-      return m_memberDef->isAttribute();
-    }
-    TemplateVariant isUNOProperty() const
-    {
-      return m_memberDef->isUNOProperty();
-    }
-    TemplateVariant isReadonly() const
-    {
-      return m_memberDef->isReadonly();
-    }
-    TemplateVariant isBound() const
-    {
-      return m_memberDef->isBound();
-    }
-    TemplateVariant isConstrained() const
-    {
-      return m_memberDef->isConstrained();
-    }
-    TemplateVariant isTransient() const
-    {
-      return m_memberDef->isTransient();
-    }
-    TemplateVariant isMaybeVoid() const
-    {
-      return m_memberDef->isMaybeVoid();
-    }
-    TemplateVariant isMaybeDefault() const
-    {
-      return m_memberDef->isMaybeDefault();
-    }
-    TemplateVariant isMaybeAmbiguous() const
-    {
-      return m_memberDef->isMaybeAmbiguous();
-    }
-    TemplateVariant isPublished() const
-    {
-      return m_memberDef->isPublished();
-    }
-    TemplateVariant isTemplateSpecialization() const
-    {
-      return m_memberDef->isTemplateSpecialization();
-    }
-    TemplateVariant isProperty() const
-    {
-      return m_memberDef->isProperty();
-    }
-    TemplateVariant isEnumValue() const
-    {
-      return m_memberDef->isEnumValue();
-    }
-    TemplateVariant isVariable() const
-    {
-      return m_memberDef->isVariable();
-    }
-    TemplateVariant isEnumeration() const
-    {
-      return m_memberDef->isEnumerate();
-    }
-    TemplateVariant hasDetails() const
-    {
-      return m_memberDef->hasDetailedDescription();
-    }
-    TemplateVariant initializer() const
-    {
-      return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->initializer());
-    }
-    TemplateVariant initializerAsCode() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.initializerParsed)
-      {
-        QCString scopeName;
-        if (m_memberDef->getClassDef())
-        {
-          scopeName = m_memberDef->getClassDef()->name();
-        }
-        else if (m_memberDef->getNamespaceDef())
-        {
-          scopeName = m_memberDef->getNamespaceDef()->name();
-        }
-        cache.initializer = parseCode(m_memberDef,
-                                      scopeName,relPathAsString(),
-                                      m_memberDef->initializer());
-        cache.initializerParsed = TRUE;
-      }
-      return cache.initializer;
-    }
-    TemplateVariant isDefine() const
-    {
-      return m_memberDef->isDefine();
-    }
-    TemplateVariant isAnonymous() const
-    {
-      return m_memberDef->isAnonymous();
-    }
-    TemplateVariant anonymousType() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.anonymousType)
+      if (hasCallGraph().toBool())
       {
-        const ClassDef *cd = m_memberDef->getClassDefOfAnonymousType();
-        if (cd)
+        DotCallGraphPtr cg = getCallGraph();
+        TextStream t;
+        switch (g_globals.outputFormat)
         {
-          cache.anonymousType.reset(ClassContext::alloc(cd));
+          case ContextOutputFormat_Html:
+            {
+              cg->writeGraph(t,GOF_BITMAP,EOF_Html,
+                  g_globals.outputDir,
+                  g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_memberDef->getOutputFileBase()),
+                  relPathAsString(),TRUE,g_globals.dynSectionId
+                  );
+            }
+            break;
+          case ContextOutputFormat_Latex:
+            {
+              cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
+                  g_globals.outputDir,
+                  g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+".tex",
+                  relPathAsString(),TRUE,g_globals.dynSectionId
+                  );
+            }
+            break;
+            // TODO: support other generators
+          default:
+            err("context.cpp: output format not yet supported\n");
+            break;
         }
-      }
-      if (cache.anonymousType)
-      {
-        return cache.anonymousType.get();
+        g_globals.dynSectionId++;
+        return TemplateVariant(t.str().c_str(),TRUE);
       }
       else
       {
-        return FALSE;
+        return TemplateVariant("");
       }
     }
-    TemplateVariant anonymousMember() const
+    TemplateVariant referencedByRelation() const
     {
-      Cachable &cache = getCache();
-      if (!cache.anonymousMember)
-      {
-        MemberDef *md = m_memberDef->fromAnonymousMember();
-        if (md)
-        {
-          cache.anonymousMember.reset(MemberContext::alloc(md));
-        }
-      }
-      if (cache.anonymousMember)
-      {
-        return cache.anonymousMember.get();
-      }
-      else
+      if (hasReferencedByRelation().toBool())
       {
-        return FALSE;
+        err("context.cpp: referencedByRelation not yet implemented\n");
       }
+      return TemplateVariant("");
     }
-    TemplateVariant isRelated() const
-    {
-      return m_memberDef->isRelated();
-    }
-    TemplateVariant enumBaseType() const
-    {
-      return m_memberDef->enumBaseType();
-    }
-    TemplateVariant hasOneLineInitializer() const
-    {
-      return m_memberDef->hasOneLineInitializer();
-    }
-    TemplateVariant hasMultiLineInitializer() const
+    TemplateVariant hasCallerGraph() const
     {
-      return m_memberDef->hasMultiLineInitializer();
+      static bool haveDot = Config_getBool(HAVE_DOT);
+      if (m_memberDef->hasCallerGraph() && haveDot &&
+          (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal()))
+      {
+        DotCallGraphPtr cg = getCallerGraph();
+        return !cg->isTooBig() && !cg->isTrivial();
+      }
+      return TemplateVariant(FALSE);
     }
-    TemplateVariant enumValues() const
+    TemplateVariant callerGraph() const
     {
-      if (m_memberDef->isEnumerate())
+      if (hasCallerGraph().toBool())
       {
-        Cachable &cache = getCache();
-        if (!cache.enumValues)
+        DotCallGraphPtr cg = getCallerGraph();
+        TextStream t;
+        switch (g_globals.outputFormat)
         {
-          MemberVector mv = m_memberDef->enumFieldList();
-          cache.enumValues.reset(MemberListContext::alloc(std::move(mv)));
+          case ContextOutputFormat_Html:
+            {
+              cg->writeGraph(t,GOF_BITMAP,EOF_Html,
+                  g_globals.outputDir,
+                  g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_memberDef->getOutputFileBase()),
+                  relPathAsString(),TRUE,g_globals.dynSectionId
+                  );
+            }
+            break;
+          case ContextOutputFormat_Latex:
+            {
+              cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
+                  g_globals.outputDir,
+                  g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+".tex",
+                  relPathAsString(),TRUE,g_globals.dynSectionId
+                  );
+            }
+            break;
+            // TODO: support other generators
+          default:
+            err("context.cpp: output format not yet supported\n");
+            break;
         }
-        return cache.enumValues.get();
+        g_globals.dynSectionId++;
+        return TemplateVariant(t.str().c_str(),TRUE);
       }
       else
       {
-        return TemplateVariant(FALSE);
+        return TemplateVariant("");
       }
     }
-    TemplateVariant templateArgs() const
+    TemplateVariant referencesRelation() const
     {
-      Cachable &cache = getCache();
-      if (!cache.templateArgs && !m_memberDef->templateArguments().empty())
+      if (hasReferencesRelation().toBool())
       {
-        cache.templateArgs.reset(ArgumentListContext::alloc(m_memberDef->templateArguments(),m_memberDef,relPathAsString()));
+         err("context.cpp: referencesRelation not yet implemented\n");
       }
-      if (cache.templateArgs)
+      return TemplateVariant("");
+    }
+    TemplateVariant handleDetailsVisibleFor(const TemplateVariantList &args) const
+    {
+      if (args.size()==1)
       {
-        return cache.templateArgs.get();
+        QCString containerStr = args[0].toString();
+        MemberListContainer                 container = MemberListContainer::Class;
+        if      (containerStr=="module")    container = MemberListContainer::Group;
+        else if (containerStr=="file")      container = MemberListContainer::File;
+        else if (containerStr=="namespace") container = MemberListContainer::Namespace;
+        return m_memberDef->isDetailedSectionVisible(container);
       }
       else
       {
-        return TemplateVariant(FALSE);
-      }
-    }
-    TemplateVariant templateAlias() const
-    {
-      if (m_memberDef->isTypeAlias())
-      {
-        return createLinkedText(m_memberDef,relPathAsString(),
-                                QCString(" = ")+m_memberDef->typeString());
+        err(".detailsVisibleFor should take one string argument, got %zu\n",args.size());
       }
-      return "";
-    }
-    TemplateVariant propertyAttrs() const
-    {
-      return getCache().propertyAttrs.get();
+      return TemplateVariant();
     }
-    TemplateVariant eventAttrs() const
+    TemplateVariant detailsVisibleFor() const
     {
-      return getCache().eventAttrs.get();
+      return TemplateVariant(std::bind(&Private::handleDetailsVisibleFor,this,std::placeholders::_1));
     }
-    TemplateVariant getClass() const
+    TemplateVariant handleNameWithContextFor(const TemplateVariantList &args) const
     {
-      Cachable &cache = getCache();
-      if (!cache.classDef && m_memberDef->getClassDef())
-      {
-        cache.classDef.reset(ClassContext::alloc(m_memberDef->getClassDef()));
-      }
-      if (cache.classDef)
+      if (args.size()==1)
       {
-        return cache.classDef.get();
+        SrcLangExt lang = m_memberDef->getLanguage();
+        QCString n = m_memberDef->name();
+        QCString ctx = args[0].toString();
+        QCString sep = getLanguageSpecificSeparator(lang,TRUE);
+        if (m_memberDef->getEnumScope() && m_memberDef->livesInsideEnum())
+        {
+          n.prepend(m_memberDef->getEnumScope()->displayName()+sep);
+        }
+        if (ctx=="module" && m_memberDef->getClassDef() && !m_memberDef->isRelated())
+        {
+          n.prepend(m_memberDef->getClassDef()->displayName()+sep);
+        }
+        else if ((ctx=="module" || ctx=="file") && m_memberDef->getNamespaceDef())
+        {
+          n.prepend(m_memberDef->getNamespaceDef()->displayName()+sep);
+        }
+        return n;
       }
       else
       {
-        return TemplateVariant(FALSE);
+        err(".nameWithContextFor should take one string argument, got %zu\n",args.size());
       }
+      return TemplateVariant();
     }
-    TemplateVariant category() const
+    TemplateVariant nameWithContextFor() const
     {
-      Cachable &cache = getCache();
-      if (!cache.category && m_memberDef->category())
-      {
-        cache.category.reset(ClassContext::alloc(m_memberDef->category()));
-      }
-      if (cache.category)
-      {
-        return cache.category.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
+      return TemplateVariant(std::bind(&Private::handleNameWithContextFor,this,std::placeholders::_1));
     }
-    TemplateVariant categoryRelation() const
+
+  private:
+
+    TemplateVariant createTemplateArgs() const
     {
-      Cachable &cache = getCache();
-      if (!cache.categoryRelation && m_memberDef->categoryRelation())
-      {
-        cache.categoryRelation.reset(MemberContext::alloc(m_memberDef->categoryRelation()));
-      }
-      if (cache.categoryRelation)
-      {
-        return cache.categoryRelation.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
+      return !m_memberDef->templateArguments().empty() ?
+         TemplateVariant(ArgumentListContext::alloc(m_memberDef->templateArguments(),m_memberDef,relPathAsString())) :
+         TemplateVariant(false);
     }
-    TemplateVariant getFile() const
+    TemplateVariant createTemplateAlias() const
     {
-      Cachable &cache = getCache();
-      if (!cache.fileDef && m_memberDef->getFileDef())
-      {
-        cache.fileDef.reset(FileContext::alloc(m_memberDef->getFileDef()));
-      }
-      if (cache.fileDef)
-      {
-        return cache.fileDef.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
+      return m_memberDef->isTypeAlias() ?
+         TemplateVariant(createLinkedText(m_memberDef,relPathAsString(),
+                                QCString(" = ")+m_memberDef->typeString())) :
+         TemplateVariant("");
     }
-    TemplateVariant getNamespace() const
+    TemplateVariant createPropertyAttrs() const
     {
-      Cachable &cache = getCache();
-      if (!cache.namespaceDef && m_memberDef->getNamespaceDef())
-      {
-        cache.namespaceDef.reset(NamespaceContext::alloc(m_memberDef->getNamespaceDef()));
-      }
-      if (cache.namespaceDef)
+      TemplateVariantList list;
+      list.reserve(6);
+      if (m_memberDef->isProperty())
       {
-        return cache.namespaceDef.get();
+        if (m_memberDef->isGettable())           list.push_back("get");
+        if (m_memberDef->isPrivateGettable())    list.push_back("private get");
+        if (m_memberDef->isProtectedGettable())  list.push_back("protected get");
+        if (m_memberDef->isSettable())           list.push_back("set");
+        if (m_memberDef->isPrivateSettable())    list.push_back("private set");
+        if (m_memberDef->isProtectedSettable())  list.push_back("protected set");
       }
-      else
+      return TemplateImmutableList::alloc(list);
+    }
+    TemplateVariant createEventAttrs() const
+    {
+      TemplateVariantList list;
+      list.reserve(3);
+      if (m_memberDef->isEvent())
       {
-        return TemplateVariant(FALSE);
+        if (m_memberDef->isAddable())   list.push_back("add");
+        if (m_memberDef->isRemovable()) list.push_back("remove");
+        if (m_memberDef->isRaisable())  list.push_back("raise");
       }
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant definition() const
+    TemplateVariant createParameters() const
     {
-      return createLinkedText(m_memberDef,relPathAsString(),
-                              m_memberDef->displayDefinition());
+      const ArgumentList &defArgList = getDefArgList();
+      return !m_memberDef->isProperty() ?
+          ArgumentListContext::alloc(defArgList,m_memberDef,relPathAsString()) :
+          ArgumentListContext::alloc();
     }
-    const ArgumentList &getDefArgList() const
+    TemplateVariant createEnumValues() const
     {
-      return (m_memberDef->isDocsForDefinition()) ?
-              m_memberDef->argumentList() : m_memberDef->declArgumentList();
+      return m_memberDef->isEnumerate() ?
+          TemplateVariant(MemberListContext::alloc(m_memberDef->enumFieldList())) :
+          TemplateVariant(false);
     }
-    TemplateVariant parameters() const
+    TemplateVariant createFileDef() const
     {
-      Cachable &cache = getCache();
-      if (!cache.arguments)
-      {
-        const ArgumentList &defArgList = getDefArgList();
-        if (!m_memberDef->isProperty())
-        {
-          cache.arguments.reset(ArgumentListContext::alloc(defArgList,m_memberDef,relPathAsString()));
-        }
-        else
-        {
-          cache.arguments.reset(ArgumentListContext::alloc());
-        }
-      }
-      return cache.arguments.get();
+      return m_memberDef->getFileDef() ?
+          TemplateVariant(FileContext::alloc(m_memberDef->getFileDef())) :
+          TemplateVariant(false);
     }
-    TemplateVariant hasParameters() const
+    TemplateVariant createNamespaceDef() const
     {
-      return !getDefArgList().empty();
+      return m_memberDef->getNamespaceDef() ?
+          TemplateVariant(NamespaceContext::alloc(m_memberDef->getNamespaceDef())) :
+          TemplateVariant(false);
     }
-    TemplateVariant hasConstQualifier() const
+    TemplateVariant createClassDef() const
     {
-      return getDefArgList().constSpecifier();
+      return m_memberDef->getClassDef() ?
+          TemplateVariant(ClassContext::alloc(m_memberDef->getClassDef())) :
+          TemplateVariant(false);
     }
-    TemplateVariant hasVolatileQualifier() const
+    TemplateVariant createCategory() const
     {
-      return getDefArgList().volatileSpecifier();
+      return m_memberDef->category() ?
+          TemplateVariant(ClassContext::alloc(m_memberDef->category())) :
+          TemplateVariant(false);
     }
-    TemplateVariant hasRefQualifierLValue() const
+    TemplateVariant createCategoryRelation() const
     {
-      return getDefArgList().refQualifier()==RefQualifierLValue;
+      return m_memberDef->categoryRelation() ?
+          TemplateVariant(MemberContext::alloc(m_memberDef->categoryRelation())) :
+          TemplateVariant(false);
     }
-    TemplateVariant hasRefQualifierRValue() const
+    TemplateVariant createDefinition() const
     {
-      return getDefArgList().refQualifier()==RefQualifierRValue;
+      return createLinkedText(m_memberDef,relPathAsString(),
+                              m_memberDef->displayDefinition());
     }
-    TemplateVariant trailingReturnType() const
+    TemplateVariant createTrailingReturnType() const
     {
       const ArgumentList &al = getDefArgList();
-      if (!al.trailingReturnType().isEmpty())
-      {
-        return createLinkedText(m_memberDef,relPathAsString(),
-                                al.trailingReturnType());
-      }
-      else
-      {
-        return "";
-      }
-    }
-    TemplateVariant extraTypeChars() const
-    {
-      return m_memberDef->extraTypeChars();
+      return !al.trailingReturnType().isEmpty() ?
+          TemplateVariant(createLinkedText(m_memberDef,relPathAsString(), al.trailingReturnType())) :
+          TemplateVariant("");
     }
-    void addTemplateDecls(TemplateList *tl) const
+    TemplateVariant createTemplateDecls() const
     {
+      TemplateVariantList list;
       const ClassDef *cd=m_memberDef->getClassDef();
       if (!m_memberDef->definitionTemplateParameterLists().empty())
       {
@@ -4770,8 +4002,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
         {
           if (!tal.empty())
           {
-            ArgumentListContext *al = ArgumentListContext::alloc(tal,m_memberDef,relPathAsString());
-            tl->append(al);
+            list.push_back(ArgumentListContext::alloc(tal,m_memberDef,relPathAsString()));
           }
         }
       }
@@ -4783,520 +4014,409 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
           {
             if (!tal.empty())
             {
-              ArgumentListContext *al = ArgumentListContext::alloc(tal,m_memberDef,relPathAsString());
-              tl->append(al);
+              list.push_back(ArgumentListContext::alloc(tal,m_memberDef,relPathAsString()));
             }
           }
         }
         if (!m_memberDef->templateArguments().empty()) // function template prefix
         {
-          ArgumentListContext *al = ArgumentListContext::alloc(
-              m_memberDef->templateArguments(),m_memberDef,relPathAsString());
-          tl->append(al);
+          list.push_back(ArgumentListContext::alloc(
+                       m_memberDef->templateArguments(),m_memberDef,relPathAsString()));
         }
       }
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant templateDecls() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.templateDecls)
-      {
-        TemplateList *tl = TemplateList::alloc();
-        addTemplateDecls(tl);
-        cache.templateDecls.reset(tl);
-      }
-      return cache.templateDecls.get();
-    }
-    TemplateVariant labels() const
+    TemplateVariant createAnonymousType() const
     {
-      Cachable &cache = getCache();
-      if (!cache.labels)
-      {
-        StringVector sl = m_memberDef->getLabels(m_memberDef->getOuterScope());
-        TemplateList *tl = TemplateList::alloc();
-        for (const auto &s : sl)
-        {
-          tl->append(s.c_str());
-        }
-        cache.labels.reset(tl);
-      }
-      return cache.labels.get();
+      const ClassDef *cd = m_memberDef->getClassDefOfAnonymousType();
+      return cd ? TemplateVariant(ClassContext::alloc(cd)) : TemplateVariant(false);
     }
-    TemplateVariant paramDocs() const
+    TemplateVariant createParamDocs() const
     {
-      Cachable &cache = getCache();
-      if (!cache.paramDocs)
+      if (m_memberDef->argumentList().hasDocumentation())
       {
-        if (m_memberDef->argumentList().hasDocumentation())
+        QCString paramDocs;
+        for (const Argument &a : m_memberDef->argumentList())
         {
-          QCString paramDocs;
-          for (const Argument &a : m_memberDef->argumentList())
+          if (a.hasDocumentation())
           {
-            if (a.hasDocumentation())
-            {
-              QCString docs = a.docs;
-              QCString direction = extractDirection(docs);
-              paramDocs+="@param"+direction+" "+a.name+" "+docs;
-            }
+            QCString docs = a.docs;
+            QCString direction = extractDirection(docs);
+            paramDocs+="@param"+direction+" "+a.name+" "+docs;
           }
-          cache.paramDocs.reset(new TemplateVariant(parseDoc(m_memberDef,
-                                           m_memberDef->docFile(),m_memberDef->docLine(),
-                                           relPathAsString(),paramDocs,FALSE)));
-        }
-        else
-        {
-          cache.paramDocs.reset(new TemplateVariant(""));
         }
+        return TemplateVariant(parseDoc(m_memberDef,
+                                        m_memberDef->docFile(),m_memberDef->docLine(),
+                                        relPathAsString(),paramDocs,FALSE));
       }
-      return *cache.paramDocs;
+      return TemplateVariant("");
     }
-    TemplateVariant implements() const
+    TemplateVariant createImplements() const
     {
-      Cachable &cache = getCache();
-      if (!cache.implements)
+      const MemberDef *md = m_memberDef->reimplements();
+      TemplateVariantList list;
+      if (md)
       {
-        const MemberDef *md = m_memberDef->reimplements();
-        cache.implements.reset(TemplateList::alloc());
-        if (md)
+        const ClassDef *cd = md->getClassDef();
+        // filter on pure virtual/interface methods
+        if (cd && (md->virtualness()==Pure || cd->compoundType()==ClassDef::Interface))
         {
-          const ClassDef *cd = md->getClassDef();
-          // filter on pure virtual/interface methods
-          if (cd && (md->virtualness()==Pure || cd->compoundType()==ClassDef::Interface))
-          {
-            MemberContext *mc = MemberContext::alloc(md);
-            cache.implements->append(mc);
-          }
+          list.push_back(MemberContext::alloc(md));
         }
       }
-      return cache.implements.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant reimplements() const
+    TemplateVariant createReimplements() const
     {
-      Cachable &cache = getCache();
-      if (!cache.reimplements)
+      const MemberDef *md = m_memberDef->reimplements();
+      TemplateVariantList list;
+      if (md)
       {
-        const MemberDef *md = m_memberDef->reimplements();
-        cache.reimplements.reset(TemplateList::alloc());
-        if (md)
+        const ClassDef *cd = md->getClassDef();
+        // filter on non-pure virtual & non interface methods
+        if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface)
         {
-          const ClassDef *cd = md->getClassDef();
-          // filter on non-pure virtual & non interface methods
-          if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface)
-          {
-            MemberContext *mc = MemberContext::alloc(md);
-            cache.reimplements->append(mc);
-          }
+          list.push_back(MemberContext::alloc(md));
         }
       }
-      return cache.reimplements.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant implementedBy() const
+    TemplateVariant createImplementedBy() const
     {
-      Cachable &cache = getCache();
-      if (!cache.implementedBy)
+      TemplateVariantList list;
+      list.reserve(m_memberDef->reimplementedBy().size());
+      for (const auto &md : m_memberDef->reimplementedBy())
       {
-        cache.implementedBy.reset(TemplateList::alloc());
-        for (const auto &md : m_memberDef->reimplementedBy())
+        const ClassDef *cd = md->getClassDef();
+        // filter on pure virtual/interface methods
+        if (cd && md->virtualness()==Pure && cd->compoundType()==ClassDef::Interface)
         {
-          const ClassDef *cd = md->getClassDef();
-          // filter on pure virtual/interface methods
-          if (cd && md->virtualness()==Pure && cd->compoundType()==ClassDef::Interface)
-          {
-            MemberContext *mc = new MemberContext(md);
-            cache.implementedBy->append(mc);
-          }
+          list.push_back(MemberContext::alloc(md));
         }
       }
-      return cache.implementedBy.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant reimplementedBy() const
+    TemplateVariant createReimplementedBy() const
     {
-      Cachable &cache = getCache();
-      if (!cache.reimplementedBy)
+      TemplateVariantList list;
+      list.reserve(m_memberDef->reimplementedBy().size());
+      for (const auto &md : m_memberDef->reimplementedBy())
       {
-        cache.reimplementedBy.reset(TemplateList::alloc());
-        for (const auto &md : m_memberDef->reimplementedBy())
+        const ClassDef *cd = md->getClassDef();
+        // filter on non-pure virtual & non interface methods
+        if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface)
         {
-          const ClassDef *cd = md->getClassDef();
-          // filter on non-pure virtual & non interface methods
-          if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface)
-          {
-            MemberContext *mc = new MemberContext(md);
-            cache.reimplementedBy->append(mc);
-          }
+          list.push_back(MemberContext::alloc(md));
         }
       }
-      return cache.reimplementedBy.get();
+      return TemplateImmutableList::alloc(list);
     }
-    void addExamples(TemplateList *list) const
+    TemplateVariant createExamples() const
     {
+      TemplateVariantList list;
       if (m_memberDef->hasExamples())
       {
+        list.reserve(m_memberDef->getExamples().size());
         for (const auto &ex : m_memberDef->getExamples())
         {
-          TemplateStruct *s = TemplateStruct::alloc();
-          s->set("text",ex.name);
-          s->set("isLinkable",TRUE);
-          s->set("anchor",ex.anchor);
-          s->set("fileName",ex.file);
-          s->set("isReference",FALSE);
-          s->set("externalReference","");
-          list->append(s);
-        }
-      }
-    }
-    TemplateVariant examples() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.examples)
-      {
-        TemplateList *exampleList = TemplateList::alloc();
-        addExamples(exampleList);
-        cache.examples.reset(exampleList);
-      }
-      return cache.examples.get();
-    }
-    TemplateVariant typeConstraints() const
-    {
-      Cachable &cache = getCache();
-      if (cache.typeConstraints && !m_memberDef->typeConstraints().empty())
-      {
-        cache.typeConstraints.reset(ArgumentListContext::alloc(m_memberDef->typeConstraints(),m_memberDef,relPathAsString()));
-      }
-      else
-      {
-        cache.typeConstraints.reset(ArgumentListContext::alloc());
-      }
-      return cache.typeConstraints.get();
-    }
-    TemplateVariant functionQualifier() const
-    {
-      if (!m_memberDef->isObjCMethod() &&
-          (m_memberDef->isFunction()  || m_memberDef->isSlot() ||
-           m_memberDef->isPrototype() || m_memberDef->isSignal()
-          )
-         )
-      {
-        return "()";
-      }
-      else
-      {
-        return "";
-      }
-    }
-    TemplateVariant sourceRefs() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.sourceRefs)
-      {
-        cache.sourceRefs.reset(MemberListContext::alloc(m_memberDef->getReferencesMembers()));
-      }
-      return cache.sourceRefs.get();
-    }
-    TemplateVariant sourceRefBys() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.sourceRefBys)
-      {
-        cache.sourceRefBys.reset(MemberListContext::alloc(m_memberDef->getReferencedByMembers()));
-      }
-      return cache.sourceRefBys.get();
-    }
-    TemplateVariant hasSources() const
-    {
-      return TemplateVariant(m_memberDef->hasSources());
-    }
-    TemplateVariant sourceCode() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.sourceCodeParsed)
-      {
-        QCString codeFragment;
-        const FileDef *fd   = m_memberDef->getBodyDef();
-        int startLine = m_memberDef->getStartBodyLine();
-        int endLine   = m_memberDef->getEndBodyLine();
-        if (fd && readCodeFragment(fd->absFilePath(),
-              startLine,endLine,codeFragment)
-           )
-        {
-          QCString scopeName;
-          if (m_memberDef->getClassDef())
-          {
-            scopeName = m_memberDef->getClassDef()->name();
-          }
-          else if (m_memberDef->getNamespaceDef())
+          TemplateStructIntfPtr s = TemplateImmutableStruct::alloc(
           {
-            scopeName = m_memberDef->getNamespaceDef()->name();
-          }
-          cache.sourceCode = parseCode(m_memberDef,
-                                       scopeName,relPathAsString(),
-                                       codeFragment,startLine,endLine,TRUE);
-          cache.sourceCodeParsed = TRUE;
-        }
-      }
-      return cache.sourceCode;
-    }
-    DotCallGraph *getCallGraph() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.callGraph)
-      {
-        cache.callGraph.reset(new DotCallGraph(m_memberDef,FALSE));
-      }
-      return cache.callGraph.get();
-    }
-    TemplateVariant hasCallGraph() const
-    {
-      static bool haveDot = Config_getBool(HAVE_DOT);
-      if (m_memberDef->hasCallGraph() && haveDot &&
-          (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal()))
-      {
-        DotCallGraph *cg = getCallGraph();
-        return !cg->isTooBig() && !cg->isTrivial();
-      }
-      return TemplateVariant(FALSE);
-    }
-    TemplateVariant hasReferencedByRelation() const
-    {
-      return TemplateVariant(m_memberDef->hasReferencedByRelation());
-    }
-    TemplateVariant callGraph() const
-    {
-      if (hasCallGraph().toBool())
-      {
-        DotCallGraph *cg = getCallGraph();
-        TextStream t;
-        switch (g_globals.outputFormat)
-        {
-          case ContextOutputFormat_Html:
-            {
-              cg->writeGraph(t,GOF_BITMAP,EOF_Html,
-                  g_globals.outputDir,
-                  g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+Doxygen::htmlFileExtension,
-                  relPathAsString(),TRUE,g_globals.dynSectionId
-                  );
-            }
-            break;
-          case ContextOutputFormat_Latex:
-            {
-              cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
-                  g_globals.outputDir,
-                  g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+".tex",
-                  relPathAsString(),TRUE,g_globals.dynSectionId
-                  );
-            }
-            break;
-            // TODO: support other generators
-          default:
-            err("context.cpp: output format not yet supported\n");
-            break;
+            { "text",             TemplateVariant(ex.name)   },
+            { "isLinkable",       TemplateVariant(TRUE)      },
+            { "anchor",           TemplateVariant(ex.anchor) },
+            { "fileName",         TemplateVariant(ex.file)   },
+            { "isReference",      TemplateVariant(FALSE)     },
+            { "externalReference",TemplateVariant("")        }
+          });
+          list.push_back(s);
         }
-        g_globals.dynSectionId++;
-        return TemplateVariant(t.str().c_str(),TRUE);
-      }
-      else
-      {
-        return TemplateVariant("");
-      }
-    }
-    TemplateVariant referencedByRelation() const
-    {
-      if (hasReferencedByRelation().toBool())
-      {
-        err("context.cpp: output format not yet supported\n");
-      }
-      return TemplateVariant("");
-    }
-    DotCallGraph *getCallerGraph() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.callerGraph)
-      {
-        cache.callerGraph.reset(new DotCallGraph(m_memberDef,TRUE));
-      }
-      return cache.callerGraph.get();
-    }
-    TemplateVariant hasCallerGraph() const
-    {
-      static bool haveDot = Config_getBool(HAVE_DOT);
-      if (m_memberDef->hasCallerGraph() && haveDot &&
-          (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal()))
-      {
-        DotCallGraph *cg = getCallerGraph();
-        return !cg->isTooBig() && !cg->isTrivial();
-      }
-      return TemplateVariant(FALSE);
-    }
-    TemplateVariant hasReferencesRelation() const
-    {
-      return TemplateVariant(m_memberDef->hasReferencesRelation());
-    }
-    TemplateVariant callerGraph() const
-    {
-      if (hasCallerGraph().toBool())
-      {
-        DotCallGraph *cg = getCallerGraph();
-        TextStream t;
-        switch (g_globals.outputFormat)
-        {
-          case ContextOutputFormat_Html:
-            {
-              cg->writeGraph(t,GOF_BITMAP,EOF_Html,
-                  g_globals.outputDir,
-                  g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+Doxygen::htmlFileExtension,
-                  relPathAsString(),TRUE,g_globals.dynSectionId
-                  );
-            }
-            break;
-          case ContextOutputFormat_Latex:
-            {
-              cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
-                  g_globals.outputDir,
-                  g_globals.outputDir+Portable::pathSeparator()+m_memberDef->getOutputFileBase()+".tex",
-                  relPathAsString(),TRUE,g_globals.dynSectionId
-                  );
-            }
-            break;
-            // TODO: support other generators
-          default:
-            err("context.cpp: output format not yet supported\n");
-            break;
-        }
-        g_globals.dynSectionId++;
-        return TemplateVariant(t.str().c_str(),TRUE);
-      }
-      else
-      {
-        return TemplateVariant("");
       }
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant referencesRelation() const
+    TemplateVariant createSourceRefs() const
     {
-      if (hasReferencesRelation().toBool())
+      return MemberListContext::alloc(m_memberDef->getReferencesMembers());
+    }
+    TemplateVariant createSourceRefBys() const
+    {
+      return MemberListContext::alloc(m_memberDef->getReferencedByMembers());
+    }
+    DotCallGraphPtr createCallGraph() const
+    {
+      return std::make_shared<DotCallGraph>(m_memberDef,FALSE);
+    }
+    DotCallGraphPtr createCallerGraph() const
+    {
+      return std::make_shared<DotCallGraph>(m_memberDef,TRUE);
+    }
+    TemplateVariant createAnonymousMember() const
+    {
+      return m_memberDef->fromAnonymousMember() ?
+          TemplateVariant(MemberContext::alloc(m_memberDef)) :
+          TemplateVariant(false);
+    }
+    TemplateVariant createLabels() const
+    {
+      StringVector sl = m_memberDef->getLabels(m_memberDef->getOuterScope());
+      TemplateVariantList list;
+      list.reserve(sl.size());
+      for (const auto &s : sl)
       {
-         err("context.cpp: output format not yet supported\n");
+        list.push_back(s.c_str());
       }
-      return TemplateVariant("");
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant type() const
+    TemplateVariant createTypeConstraints() const
     {
-      return m_memberDef->typeString();
+      return !m_memberDef->typeConstraints().empty() ?
+          TemplateVariant(ArgumentListContext::alloc(m_memberDef->typeConstraints(),m_memberDef,relPathAsString())) :
+          TemplateVariant(ArgumentListContext::alloc());
     }
-    TemplateVariant handleDetailsVisibleFor(const std::vector<TemplateVariant> &args) const
+    TemplateVariant createInitializerAsCode() const
     {
-      if (args.size()==1)
+      QCString scopeName;
+      if (m_memberDef->getClassDef())
       {
-        QCString containerStr = args[0].toString();
-        MemberListContainer                 container = MemberListContainer::Class;
-        if      (containerStr=="module")    container = MemberListContainer::Group;
-        else if (containerStr=="file")      container = MemberListContainer::File;
-        else if (containerStr=="namespace") container = MemberListContainer::Namespace;
-        return m_memberDef->isDetailedSectionVisible(container);
+        scopeName = m_memberDef->getClassDef()->name();
       }
-      else
+      else if (m_memberDef->getNamespaceDef())
       {
-        err(".detailsVisibleFor should take one string argument, got %zu\n",args.size());
+        scopeName = m_memberDef->getNamespaceDef()->name();
       }
-      return TemplateVariant();
+      return TemplateVariant(parseCode(m_memberDef,
+                                       scopeName,relPathAsString(),
+                                       m_memberDef->initializer()));
     }
-    TemplateVariant detailsVisibleFor() const
+    TemplateVariant createInitializer() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleDetailsVisibleFor>(this);
+      return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->initializer());
     }
-    TemplateVariant handleNameWithContextFor(const std::vector<TemplateVariant> &args) const
+    TemplateVariant createSourceCode() const
     {
-      if (args.size()==1)
+      QCString codeFragment;
+      const FileDef *fd = m_memberDef->getBodyDef();
+      int startLine = m_memberDef->getStartBodyLine();
+      int endLine   = m_memberDef->getEndBodyLine();
+      if (fd && readCodeFragment(fd->absFilePath(),startLine,endLine,codeFragment))
       {
-        SrcLangExt lang = m_memberDef->getLanguage();
-        QCString n = m_memberDef->name();
-        QCString ctx = args[0].toString();
-        QCString sep = getLanguageSpecificSeparator(lang,TRUE);
-        if (m_memberDef->getEnumScope() && m_memberDef->livesInsideEnum())
-        {
-          n.prepend(m_memberDef->getEnumScope()->displayName()+sep);
-        }
-        if (ctx=="module" && m_memberDef->getClassDef() && !m_memberDef->isRelated())
+        QCString scopeName;
+        if (m_memberDef->getClassDef())
         {
-          n.prepend(m_memberDef->getClassDef()->displayName()+sep);
+          scopeName = m_memberDef->getClassDef()->name();
         }
-        else if ((ctx=="module" || ctx=="file") && m_memberDef->getNamespaceDef())
+        else if (m_memberDef->getNamespaceDef())
         {
-          n.prepend(m_memberDef->getNamespaceDef()->displayName()+sep);
+          scopeName = m_memberDef->getNamespaceDef()->name();
         }
-        return n;
-      }
-      else
-      {
-        err(".nameWithContextFor should take one string argument, got %zu\n",args.size());
+        return parseCode(m_memberDef,
+                         scopeName,relPathAsString(),
+                         codeFragment,startLine,endLine,TRUE);
       }
-      return TemplateVariant();
+      return TemplateVariant("");
     }
-    TemplateVariant nameWithContextFor() const
+    TemplateVariant createDeclType() const
     {
-      return TemplateVariant::FunctionDelegate::fromMethod<Private,&Private::handleNameWithContextFor>(this);
+      return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->getDeclType());
     }
-  private:
+    TemplateVariant createDeclArgs() const
+    {
+      return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->argsString());
+    }
+    TemplateVariant createFieldType() const
+    {
+      return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->fieldType());
+    }
+    TemplateVariant createException() const
+    {
+      return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->excpString());
+    }
+    TemplateVariant createBitfields() const
+    {
+      return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->bitfieldString());
+    }
+
     const MemberDef *m_memberDef;
     struct Cachable : public DefinitionContext<MemberContext::Private>::Cachable
     {
-      Cachable(const MemberDef *md) : DefinitionContext<MemberContext::Private>::Cachable(md),
-                                initializerParsed(FALSE), sourceCodeParsed(FALSE),
-                                declArgsParsed(FALSE), declTypeParsed(FALSE) { }
-      SharedPtr<ArgumentListContext> templateArgs;
-      SharedPtr<ArgumentListContext> arguments;
-      SharedPtr<MemberListContext>   enumValues;
-      SharedPtr<FileContext>         fileDef;
-      SharedPtr<NamespaceContext>    namespaceDef;
-      SharedPtr<ClassContext>        category;
-      SharedPtr<MemberContext>       categoryRelation;
-      SharedPtr<ClassContext>        classDef;
-      SharedPtr<ClassContext>        anonymousType;
-      SharedPtr<TemplateList>        templateDecls;
-      std::unique_ptr<TemplateVariant>     paramDocs;
-      SharedPtr<TemplateList>        implements;
-      SharedPtr<TemplateList>        reimplements;
-      SharedPtr<TemplateList>        implementedBy;
-      SharedPtr<MemberListContext>   sourceRefs;
-      SharedPtr<MemberListContext>   sourceRefBys;
-      std::unique_ptr<DotCallGraph>        callGraph;
-      std::unique_ptr<DotCallGraph>        callerGraph;
-      SharedPtr<MemberContext>       anonymousMember;
-      SharedPtr<TemplateList>        reimplementedBy;
-      SharedPtr<TemplateList>        labels;
-      TemplateVariant                initializer;
-      bool                           initializerParsed;
-      TemplateVariant                sourceCode;
-      bool                           sourceCodeParsed;
-      TemplateVariant                declArgs;
-      bool                           declArgsParsed;
-      TemplateVariant                declType;
-      bool                           declTypeParsed;
-      SharedPtr<TemplateList>        examples;
-      SharedPtr<TemplateList>        exampleList;
-      SharedPtr<ArgumentListContext> typeConstraints;
-      SharedPtr<TemplateList>        propertyAttrs;
-      SharedPtr<TemplateList>        eventAttrs;
+      CachedItem<TemplateVariant,  Private, &Private::createTemplateArgs>       templateArgs;
+      CachedItem<TemplateVariant,  Private, &Private::createTemplateAlias>      templateAlias;
+      CachedItem<TemplateVariant,  Private, &Private::createPropertyAttrs>      propertyAttrs;
+      CachedItem<TemplateVariant,  Private, &Private::createEventAttrs>         eventAttrs;
+      CachedItem<TemplateVariant,  Private, &Private::createParameters>         parameters;
+      CachedItem<TemplateVariant,  Private, &Private::createEnumValues>         enumValues;
+      CachedItem<TemplateVariant,  Private, &Private::createFileDef>            fileDef;
+      CachedItem<TemplateVariant,  Private, &Private::createNamespaceDef>       namespaceDef;
+      CachedItem<TemplateVariant,  Private, &Private::createCategory>           category;
+      CachedItem<TemplateVariant,  Private, &Private::createCategoryRelation>   categoryRelation;
+      CachedItem<TemplateVariant,  Private, &Private::createDefinition>         definition;
+      CachedItem<TemplateVariant,  Private, &Private::createTrailingReturnType> trailingReturnType;
+      CachedItem<TemplateVariant,  Private, &Private::createTemplateDecls>      templateDecls;
+      CachedItem<TemplateVariant,  Private, &Private::createClassDef>           classDef;
+      CachedItem<TemplateVariant,  Private, &Private::createAnonymousType>      anonymousType;
+      CachedItem<TemplateVariant,  Private, &Private::createParamDocs>          paramDocs;
+      CachedItem<TemplateVariant,  Private, &Private::createImplements>         implements;
+      CachedItem<TemplateVariant,  Private, &Private::createReimplements>       reimplements;
+      CachedItem<TemplateVariant,  Private, &Private::createImplementedBy>      implementedBy;
+      CachedItem<TemplateVariant,  Private, &Private::createReimplementedBy>    reimplementedBy;
+      CachedItem<TemplateVariant,  Private, &Private::createExamples>           examples;
+      CachedItem<TemplateVariant,  Private, &Private::createSourceRefs>         sourceRefs;
+      CachedItem<TemplateVariant,  Private, &Private::createSourceRefBys>       sourceRefBys;
+      CachedItem<DotCallGraphPtr,  Private, &Private::createCallGraph>          callGraph;
+      CachedItem<DotCallGraphPtr,  Private, &Private::createCallerGraph>        callerGraph;
+      CachedItem<TemplateVariant,  Private, &Private::createAnonymousMember>    anonymousMember;
+      CachedItem<TemplateVariant,  Private, &Private::createLabels>             labels;
+      CachedItem<TemplateVariant,  Private, &Private::createTypeConstraints>    typeConstraints;
+      CachedItem<TemplateVariant,  Private, &Private::createInitializer>        initializer;
+      CachedItem<TemplateVariant,  Private, &Private::createInitializerAsCode>  initializerAsCode;
+      CachedItem<TemplateVariant,  Private, &Private::createSourceCode>         sourceCode;
+      CachedItem<TemplateVariant,  Private, &Private::createDeclArgs>           declArgs;
+      CachedItem<TemplateVariant,  Private, &Private::createDeclType>           declType;
+      CachedItem<TemplateVariant,  Private, &Private::createFieldType>          fieldType;
+      CachedItem<TemplateVariant,  Private, &Private::createException>          exception;
+      CachedItem<TemplateVariant,  Private, &Private::createBitfields>          bitfields;
     };
-    Cachable &getCache() const
-    {
-      Cachable *c = static_cast<Cachable*>(m_memberDef->cookie());
-      assert(c!=0);
-      return *c;
-    }
-    static PropertyMapper<MemberContext::Private> s_inst;
+    Cachable m_cachable;
+    static const PropertyMap<MemberContext::Private> s_inst;
+};
+
+//%% struct Member(Symbol): member information
+//%% {
+const PropertyMap<MemberContext::Private> MemberContext::Private::s_inst {
+  BASE_PROPERTIES,
+  {  "isSignal",            &Private::isSignal },
+  {  "isSlot",              &Private::isSlot },
+  {  "isVariable",          &Private::isVariable },
+  {  "isEnumeration",       &Private::isEnumeration },
+  {  "isEnumValue",         &Private::isEnumValue },
+  {  "isTypedef",           &Private::isTypedef },
+  {  "isFunction",          &Private::isFunction },
+  {  "isFunctionPtr",       &Private::isFunctionPtr },
+  {  "isDefine",            &Private::isDefine },
+  {  "isFriend",            &Private::isFriend },
+  {  "isProperty",          &Private::isProperty },
+  {  "isEvent",             &Private::isEvent },
+  {  "isRelated",           &Private::isRelated },
+  {  "isForeign",           &Private::isForeign },
+  {  "isStatic",            &Private::isStatic },
+  {  "isInline",            &Private::isInline },
+  {  "isExplicit",          &Private::isExplicit },
+  {  "isMutable",           &Private::isMutable },
+  {  "isGettable",          &Private::isGettable },
+  {  "isPrivateGettable",   &Private::isPrivateGettable },
+  {  "isProtectedGettable", &Private::isProtectedGettable },
+  {  "isSettable",          &Private::isSettable },
+  {  "isPrivateSettable",   &Private::isPrivateSettable },
+  {  "isProtectedSettable", &Private::isProtectedSettable },
+  {  "isReadable",          &Private::isReadable },
+  {  "isWritable",          &Private::isWritable },
+  {  "isAddable",           &Private::isAddable },
+  {  "isRemovable",         &Private::isRemovable },
+  {  "isRaisable",          &Private::isRaisable },
+  {  "isFinal",             &Private::isFinal },
+  {  "isAbstract",          &Private::isAbstract },
+  {  "isOverride",          &Private::isOverride },
+  {  "isInitonly",          &Private::isInitonly },
+  {  "isOptional",          &Private::isOptional },
+  {  "isRequired",          &Private::isRequired },
+  {  "isNonAtomic",         &Private::isNonAtomic },
+  {  "isCopy",              &Private::isCopy },
+  {  "isAssign",            &Private::isAssign },
+  {  "isRetain",            &Private::isRetain },
+  {  "isWeak",              &Private::isWeak },
+  {  "isStrong",            &Private::isStrong },
+  {  "isEnumStruct",        &Private::isEnumStruct },
+  {  "isUnretained",        &Private::isUnretained },
+  {  "isNew",               &Private::isNew },
+  {  "isSealed",            &Private::isSealed },
+  {  "isImplementation",    &Private::isImplementation },
+  {  "isExternal",          &Private::isExternal },
+  {  "isTypeAlias",         &Private::isTypeAlias },
+  {  "isDefault",           &Private::isDefault },
+  {  "isDelete",            &Private::isDelete },
+  {  "isNoExcept",          &Private::isNoExcept },
+  {  "isAttribute",         &Private::isAttribute },
+  {  "isUNOProperty",       &Private::isUNOProperty },
+  {  "isReadonly",          &Private::isReadonly },
+  {  "isBound",             &Private::isBound },
+  {  "isConstrained",       &Private::isConstrained },
+  {  "isTransient",         &Private::isTransient },
+  {  "isMaybeVoid",         &Private::isMaybeVoid },
+  {  "isMaybeDefault",      &Private::isMaybeDefault },
+  {  "isMaybeAmbiguous",    &Private::isMaybeAmbiguous },
+  {  "isPublished",         &Private::isPublished },
+  {  "isTemplateSpecialization",&Private::isTemplateSpecialization },
+  {  "isObjCMethod",        &Private::isObjCMethod },
+  {  "isObjCProperty",      &Private::isObjCProperty },
+  {  "isCSharpProperty",    &Private::isCSharpProperty },
+  {  "isAnonymous",         &Private::isAnonymous },
+  {  "hasParameters",       &Private::hasParameters },
+  {  "declType",            &Private::declType },
+  {  "declArgs",            &Private::declArgs },
+  {  "anonymousType",       &Private::anonymousType },
+  {  "anonymousMember",     &Private::anonymousMember },
+  {  "hasDetails",          &Private::hasDetails },
+  {  "exception",           &Private::exception },
+  {  "bitfields",           &Private::bitfields },
+  {  "initializer",         &Private::initializer },
+  {  "initializerAsCode",   &Private::initializerAsCode },
+  {  "hasOneLineInitializer",   &Private::hasOneLineInitializer },
+  {  "hasMultiLineInitializer", &Private::hasMultiLineInitializer },
+  {  "templateArgs",        &Private::templateArgs },
+  {  "templateAlias",       &Private::templateAlias },
+  {  "propertyAttrs",       &Private::propertyAttrs },
+  {  "eventAttrs",          &Private::eventAttrs },
+  {  "category",            &Private::category },
+  {  "categoryRelation",    &Private::categoryRelation },
+  {  "class",               &Private::getClass },
+  {  "file",                &Private::getFile },
+  {  "namespace",           &Private::getNamespace },
+  {  "definition",          &Private::definition },
+  {  "parameters",          &Private::parameters },
+  {  "hasConstQualifier",   &Private::hasConstQualifier },
+  {  "hasVolatileQualifier",&Private::hasVolatileQualifier },
+  {  "hasRefQualifierLValue", &Private::hasRefQualifierLValue },
+  {  "hasRefQualifierRValue", &Private::hasRefQualifierRValue },
+  {  "trailingReturnType",  &Private::trailingReturnType },
+  {  "extraTypeChars",      &Private::extraTypeChars },
+  {  "templateDecls",       &Private::templateDecls },
+  {  "labels",              &Private::labels },
+  {  "enumBaseType",        &Private::enumBaseType },
+  {  "enumValues",          &Private::enumValues },
+  {  "paramDocs",           &Private::paramDocs },
+  {  "reimplements",        &Private::reimplements },
+  {  "implements",          &Private::implements },
+  {  "reimplementedBy",     &Private::reimplementedBy },
+  {  "implementedBy",       &Private::implementedBy },
+  {  "examples",            &Private::examples },
+  {  "typeConstraints",     &Private::typeConstraints },
+  {  "functionQualifier",   &Private::functionQualifier },
+  {  "sourceRefs",          &Private::sourceRefs },
+  {  "sourceRefBys",        &Private::sourceRefBys },
+  {  "hasSources",          &Private::hasSources },
+  {  "sourceCode",          &Private::sourceCode },
+  {  "hasCallGraph",        &Private::hasCallGraph },
+  {  "callGraph",           &Private::callGraph },
+  {  "hasCallerGraph",      &Private::hasCallerGraph },
+  {  "callerGraph",         &Private::callerGraph },
+  {  "hasReferencedByRelation", &Private::hasReferencedByRelation },
+  {  "referencedByRelation",    &Private::referencedByRelation },
+  {  "hasReferencesRelation",   &Private::hasReferencesRelation },
+  {  "referencesRelation",      &Private::referencesRelation },
+  {  "fieldType",           &Private::fieldType },
+  {  "type",                &Private::type },
+  {  "detailsVisibleFor",   &Private::detailsVisibleFor },
+  {  "nameWithContextFor",  &Private::nameWithContextFor }
 };
 //%% }
 
-PropertyMapper<MemberContext::Private> MemberContext::Private::s_inst;
+//PropertyMapper<MemberContext::Private> MemberContext::Private::s_inst;
 
-MemberContext::MemberContext(const MemberDef *md) : RefCountedContext("MemberContext")
+MemberContext::MemberContext(const MemberDef *md) : p(std::make_unique<Private>(md))
 {
-  p = new Private(md);
 }
 
 MemberContext::~MemberContext()
 {
-  delete p;
 }
 
 TemplateVariant MemberContext::get(const QCString &n) const
@@ -5311,146 +4431,94 @@ StringVector MemberContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct Concept(Symbol): class information
-//%% {
 class ConceptContext::Private : public DefinitionContext<ConceptContext::Private>
 {
   public:
     Private(const ConceptDef *cd) : DefinitionContext<ConceptContext::Private>(cd),
        m_conceptDef(cd)
     {
-      static bool init=FALSE;
-      if (!init)
-      {
-        addBaseProperties(s_inst);
-        s_inst.addProperty("title",                     &Private::title);
-        s_inst.addProperty("highlight",                 &Private::highlight);
-        s_inst.addProperty("subhighlight",              &Private::subHighlight);
-        s_inst.addProperty("hasDetails",                &Private::hasDetails);
-        s_inst.addProperty("includeInfo",               &Private::includeInfo);
-        s_inst.addProperty("templateDecls",             &Private::templateDecls);
-        s_inst.addProperty("initializer",               &Private::initializer);
-        s_inst.addProperty("initializerAsCode",         &Private::initializerAsCode);
-        init=TRUE;
-      }
-      if (!cd->cookie()) { cd->setCookie(new ConceptContext::Private::Cachable(cd)); }
     }
     virtual ~Private() {}
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant title() const
-    {
-      return TemplateVariant(m_conceptDef->title());
-    }
-    TemplateVariant highlight() const
-    {
-      return TemplateVariant("concepts");
-    }
-    TemplateVariant subHighlight() const
-    {
-      return TemplateVariant("");
-    }
-    TemplateVariant hasDetails() const
-    {
-      return m_conceptDef->hasDetailedDescription();
-    }
-    TemplateVariant includeInfo() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.includeInfo && m_conceptDef->includeInfo())
-      {
-        cache.includeInfo.reset(IncludeInfoContext::alloc(m_conceptDef->includeInfo(),m_conceptDef->getLanguage()));
-      }
-      if (cache.includeInfo)
-      {
-        return cache.includeInfo.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
-    }
-    void addTemplateDecls(const ConceptDef *cd,TemplateList *tl) const
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+    // Property getters
+    TemplateVariant title() const                { return TemplateVariant(m_conceptDef->title()); }
+    TemplateVariant highlight() const            { return TemplateVariant("concepts"); }
+    TemplateVariant subHighlight() const         { return TemplateVariant(""); }
+    TemplateVariant hasDetails() const           { return m_conceptDef->hasDetailedDescription(); }
+    TemplateVariant includeInfo() const          { return m_cachable.includeInfo.get(this); }
+    TemplateVariant templateDecls() const        { return m_cachable.templateDecls.get(this); }
+    TemplateVariant initializer() const          { return m_cachable.initializer.get(this); }
+    TemplateVariant initializerAsCode() const    { return m_cachable.initializerAsCode.get(this); }
+
+  private:
+    TemplateVariant createIncludeInfo() const
     {
-      if (!cd->getTemplateParameterList().empty())
-      {
-        ArgumentListContext *al = ArgumentListContext::alloc(cd->getTemplateParameterList(),cd,relPathAsString());
-        // since a TemplateVariant does take ownership of the object, we add it
-        // a separate list just to be able to delete it and avoid a memory leak
-        tl->append(al);
-      }
+      return m_conceptDef->includeInfo() ?
+          TemplateVariant(IncludeInfoContext::alloc(m_conceptDef->includeInfo(),m_conceptDef->getLanguage())) :
+          TemplateVariant(false);
     }
-    TemplateVariant templateDecls() const
+    TemplateVariant createTemplateDecls() const
     {
-      Cachable &cache = getCache();
-      if (!cache.templateDecls)
+      TemplateVariantList list;
+      if (!m_conceptDef->getTemplateParameterList().empty())
       {
-        TemplateList *tl = TemplateList::alloc();
-        addTemplateDecls(m_conceptDef,tl);
-        cache.templateDecls.reset(tl);
+        list.push_back(ArgumentListContext::alloc(m_conceptDef->getTemplateParameterList(),m_conceptDef,relPathAsString()));
       }
-      return cache.templateDecls.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant initializer() const
+    TemplateVariant createInitializer() const
     {
       return createLinkedText(m_conceptDef,relPathAsString(),m_conceptDef->initializer());
     }
-    TemplateVariant initializerAsCode() const
+    TemplateVariant createInitializerAsCode() const
     {
-      Cachable &cache = getCache();
-      if (!cache.initializerParsed)
+      QCString scopeName;
+      if (m_conceptDef->getOuterScope()!=Doxygen::globalScope)
       {
-        QCString scopeName;
-        if (m_conceptDef->getOuterScope()!=Doxygen::globalScope)
-        {
-          scopeName = m_conceptDef->getOuterScope()->name();
-        }
-        cache.initializer = parseCode(m_conceptDef,
-                                      scopeName,relPathAsString(),
-                                      m_conceptDef->initializer());
-        cache.initializerParsed = TRUE;
+        scopeName = m_conceptDef->getOuterScope()->name();
       }
-      return cache.initializer;
+      return parseCode(m_conceptDef,
+                       scopeName,relPathAsString(),
+                       m_conceptDef->initializer());
     }
 
-  private:
     const ConceptDef *m_conceptDef;
     struct Cachable : public DefinitionContext<ConceptContext::Private>::Cachable
     {
-      Cachable(const ConceptDef *cd) : DefinitionContext<ConceptContext::Private>::Cachable(cd) {}
-      SharedPtr<IncludeInfoContext>     includeInfo;
-      SharedPtr<ArgumentListContext>    typeConstraints;
-      SharedPtr<TemplateList>           templateDecls;
-      TemplateVariant                   initializer;
-      bool                              initializerParsed = false;
+      CachedItem<TemplateVariant,  Private, &Private::createIncludeInfo>       includeInfo;
+      CachedItem<TemplateVariant,  Private, &Private::createTemplateDecls>     templateDecls;
+      CachedItem<TemplateVariant,  Private, &Private::createInitializer>       initializer;
+      CachedItem<TemplateVariant,  Private, &Private::createInitializerAsCode> initializerAsCode;
     };
-    Cachable &getCache() const
-    {
-      Cachable *c = static_cast<Cachable*>(m_conceptDef->cookie());
-      assert(c!=0);
-      return *c;
-    }
-    static PropertyMapper<ConceptContext::Private> s_inst;
+    Cachable m_cachable;
+    static const PropertyMap<ConceptContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<ConceptContext::Private> ConceptContext::Private::s_inst;
+//%% struct Concept(Symbol): class information
+//%% {
+const PropertyMap<ConceptContext::Private> ConceptContext::Private::s_inst {
+  BASE_PROPERTIES,
+  {  "title",                     &Private::title },
+  {  "highlight",                 &Private::highlight },
+  {  "subhighlight",              &Private::subHighlight },
+  {  "hasDetails",                &Private::hasDetails },
+  {  "includeInfo",               &Private::includeInfo },
+  {  "templateDecls",             &Private::templateDecls },
+  {  "initializer",               &Private::initializer },
+  {  "initializerAsCode",         &Private::initializerAsCode }
+};
+//%% }
 
-ConceptContext::ConceptContext(const ConceptDef *cd) : RefCountedContext("ConceptContext")
+ConceptContext::ConceptContext(const ConceptDef *cd) : p(std::make_unique<Private>(cd))
 {
-  //printf("ConceptContext::ConceptContext(%s)\n",cd?qPrint(cd->name()):"<none>");
-  p = new Private(cd);
 }
 
 ConceptContext::~ConceptContext()
 {
-  delete p;
 }
 
 TemplateVariant ConceptContext::get(const QCString &n) const
@@ -5465,93 +4533,62 @@ StringVector ConceptContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct Module(Symbol): group information
-//%% {
 class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
 {
   public:
     Private(const GroupDef *gd) : DefinitionContext<ModuleContext::Private>(gd) , m_groupDef(gd)
     {
-      static bool init=FALSE;
-      if (!init)
-      {
-        addBaseProperties(s_inst);
-        s_inst.addProperty("title",                     &Private::title);
-        s_inst.addProperty("highlight",                 &Private::highlight);
-        s_inst.addProperty("subhighlight",              &Private::subHighlight);
-        s_inst.addProperty("hasGroupGraph",             &Private::hasGroupGraph);
-        s_inst.addProperty("groupGraph",                &Private::groupGraph);
-        s_inst.addProperty("hasDetails",                &Private::hasDetails);
-        s_inst.addProperty("modules",                   &Private::modules);
-        s_inst.addProperty("dirs",                      &Private::dirs);
-        s_inst.addProperty("files",                     &Private::files);
-        s_inst.addProperty("namespaces",                &Private::namespaces);
-        s_inst.addProperty("classes",                   &Private::classes);
-        s_inst.addProperty("constantgroups",            &Private::constantgroups);
-        s_inst.addProperty("examples",                  &Private::examples);
-        s_inst.addProperty("macros",                    &Private::macros);
-        s_inst.addProperty("typedefs",                  &Private::typedefs);
-        s_inst.addProperty("enums",                     &Private::enums);
-        s_inst.addProperty("enumvalues",                &Private::enumValues);
-        s_inst.addProperty("functions",                 &Private::functions);
-        s_inst.addProperty("variables",                 &Private::variables);
-        s_inst.addProperty("signals",                   &Private::signals);
-        s_inst.addProperty("publicSlots",               &Private::publicSlots);
-        s_inst.addProperty("protectedSlots",            &Private::protectedSlots);
-        s_inst.addProperty("privateSlots",              &Private::privateSlots);
-        s_inst.addProperty("events",                    &Private::events);
-        s_inst.addProperty("properties",                &Private::properties);
-        s_inst.addProperty("friends",                   &Private::friends);
-        s_inst.addProperty("memberGroups",              &Private::memberGroups);
-        s_inst.addProperty("detailedMacros",            &Private::detailedMacros);
-        s_inst.addProperty("detailedTypedefs",          &Private::detailedTypedefs);
-        s_inst.addProperty("detailedEnums",             &Private::detailedEnums);
-        s_inst.addProperty("detailedEnumValues",        &Private::detailedEnumValues);
-        s_inst.addProperty("detailedFunctions",         &Private::detailedFunctions);
-        s_inst.addProperty("detailedVariables",         &Private::detailedVariables);
-        s_inst.addProperty("detailedSignals",           &Private::detailedSignals);
-        s_inst.addProperty("detailedPublicSlots",       &Private::detailedPublicSlots);
-        s_inst.addProperty("detailedProtectedSlots",    &Private::detailedProtectedSlots);
-        s_inst.addProperty("detailedPrivateSlots",      &Private::detailedPrivateSlots);
-        s_inst.addProperty("detailedEvents",            &Private::detailedEvents);
-        s_inst.addProperty("detailedProperties",        &Private::detailedProperties);
-        s_inst.addProperty("detailedFriends",           &Private::detailedFriends);
-        s_inst.addProperty("inlineClasses",             &Private::inlineClasses);
-        s_inst.addProperty("compoundType",              &Private::compoundType);
-        init=TRUE;
-      }
-      if (!gd->cookie()) { gd->setCookie(new ModuleContext::Private::Cachable(gd)); }
-    }
-    virtual ~Private() {}
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant title() const
-    {
-      return TemplateVariant(m_groupDef->groupTitle());
-    }
-    TemplateVariant highlight() const
-    {
-      return TemplateVariant("modules");
-    }
-    TemplateVariant subHighlight() const
-    {
-      return TemplateVariant("");
-    }
-    DotGroupCollaboration *getGroupGraph() const
-    {
-      Cachable &cache = getCache();
-      if (!cache.groupGraph)
-      {
-        cache.groupGraph.reset(new DotGroupCollaboration(m_groupDef));
-      }
-      return cache.groupGraph.get();
     }
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const     { return s_inst.get(this,n); }
+    StringVector fields() const                      { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant title() const                    { return TemplateVariant(m_groupDef->groupTitle()); }
+    TemplateVariant highlight() const                { return TemplateVariant("modules"); }
+    TemplateVariant subHighlight() const             { return TemplateVariant(""); }
+    TemplateVariant compoundType() const             { return TemplateVariant("module"); }
+    TemplateVariant hasDetails() const               { return m_groupDef->hasDetailedDescription(); }
+    TemplateVariant modules() const                  { return m_cachable.modules.get(this); }
+    TemplateVariant examples() const                 { return m_cachable.examples.get(this); }
+    TemplateVariant pages() const                    { return m_cachable.pages.get(this); }
+    TemplateVariant dirs() const                     { return m_cachable.dirs.get(this); }
+    TemplateVariant files() const                    { return m_cachable.files.get(this); }
+    TemplateVariant classes() const                  { return m_cachable.classes.get(this); }
+    TemplateVariant namespaces() const               { return m_cachable.namespaces.get(this); }
+    TemplateVariant constantgroups() const           { return m_cachable.constantgroups.get(this); }
+    TemplateVariant macros() const                   { return m_cachable.macros.get(this); }
+    TemplateVariant typedefs() const                 { return m_cachable.typedefs.get(this); }
+    TemplateVariant enums() const                    { return m_cachable.enums.get(this); }
+    TemplateVariant enumValues() const               { return m_cachable.enums.get(this); }
+    TemplateVariant functions() const                { return m_cachable.functions.get(this); }
+    TemplateVariant variables() const                { return m_cachable.variables.get(this); }
+    TemplateVariant signals() const                  { return m_cachable.signals.get(this); }
+    TemplateVariant publicSlots() const              { return m_cachable.publicSlots.get(this); }
+    TemplateVariant protectedSlots() const           { return m_cachable.protectedSlots.get(this); }
+    TemplateVariant privateSlots() const             { return m_cachable.privateSlots.get(this); }
+    TemplateVariant events() const                   { return m_cachable.events.get(this); }
+    TemplateVariant properties() const               { return m_cachable.properties.get(this); }
+    TemplateVariant friends() const                  { return m_cachable.friends.get(this); }
+    TemplateVariant memberGroups() const             { return m_cachable.memberGroups.get(this); }
+    TemplateVariant detailedMacros() const           { return m_cachable.detailedMacros.get(this); }
+    TemplateVariant detailedTypedefs() const         { return m_cachable.detailedTypedefs.get(this); }
+    TemplateVariant detailedEnums() const            { return m_cachable.detailedEnums.get(this); }
+    TemplateVariant detailedEnumValues() const       { return m_cachable.detailedEnumValues.get(this); }
+    TemplateVariant detailedFunctions() const        { return m_cachable.detailedFunctions.get(this); }
+    TemplateVariant detailedVariables() const        { return m_cachable.detailedVariables.get(this); }
+    TemplateVariant detailedSignals() const          { return m_cachable.detailedSignals.get(this); }
+    TemplateVariant detailedPublicSlots() const      { return m_cachable.detailedPublicSlots.get(this); }
+    TemplateVariant detailedProtectedSlots() const   { return m_cachable.detailedProtectedSlots.get(this); }
+    TemplateVariant detailedPrivateSlots() const     { return m_cachable.detailedPrivateSlots.get(this); }
+    TemplateVariant detailedEvents() const           { return m_cachable.detailedEvents.get(this); }
+    TemplateVariant detailedProperties() const       { return m_cachable.detailedProperties.get(this); }
+    TemplateVariant detailedFriends() const          { return m_cachable.detailedFriends.get(this); }
+    TemplateVariant inlineClasses() const            { return m_cachable.inlineClasses.get(this); }
+    DotGroupCollaborationPtr getGroupGraph() const   { return m_cachable.groupGraph.get(this); }
+
     TemplateVariant hasGroupGraph() const
     {
       bool result=FALSE;
@@ -5559,7 +4596,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
       static bool groupGraphs = Config_getBool(GROUP_GRAPHS);
       if (haveDot && groupGraphs)
       {
-        DotGroupCollaboration *graph = getGroupGraph();
+        DotGroupCollaborationPtr graph = getGroupGraph();
         result = !graph->isTrivial();
       }
       return result;
@@ -5571,7 +4608,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
       static bool groupGraphs = Config_getBool(GROUP_GRAPHS);
       if (haveDot && groupGraphs)
       {
-        DotGroupCollaboration *graph = getGroupGraph();
+        DotGroupCollaborationPtr graph = getGroupGraph();
         switch (g_globals.outputFormat)
         {
           case ContextOutputFormat_Html:
@@ -5579,7 +4616,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
               graph->writeGraph(t,GOF_BITMAP,
                                 EOF_Html,
                                 g_globals.outputDir,
-                                g_globals.outputDir+Portable::pathSeparator()+m_groupDef->getOutputFileBase()+Doxygen::htmlFileExtension,
+                                g_globals.outputDir+Portable::pathSeparator()+addHtmlExtensionIfMissing(m_groupDef->getOutputFileBase()),
                                 relPathAsString(),
                                 TRUE,
                                 g_globals.dynSectionId);
@@ -5605,371 +4642,344 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
       }
       return TemplateVariant(t.str().c_str(),TRUE);
     }
-    TemplateVariant hasDetails() const
-    {
-      return m_groupDef->hasDetailedDescription();
-    }
-    TemplateVariant modules() const
+
+  private:
+
+    TemplateVariant createModules() const
     {
-      Cachable &cache = getCache();
-      if (!cache.modules)
+      TemplateVariantList list;
+      list.reserve(m_groupDef->getSubGroups().size());
+      for (const auto &gd : m_groupDef->getSubGroups())
       {
-        TemplateList *moduleList = TemplateList::alloc();
-        for (const auto &gd : m_groupDef->getSubGroups())
+        if (gd->isVisible())
         {
-          if (gd->isVisible())
-          {
-            moduleList->append(ModuleContext::alloc(gd));
-          }
+          list.push_back(ModuleContext::alloc(gd));
         }
-        cache.modules.reset(moduleList);
       }
-      return cache.modules.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant examples() const
+    TemplateVariant createDirs() const
     {
-      Cachable &cache = getCache();
-      if (!cache.examples)
+      TemplateVariantList list;
+      list.reserve(m_groupDef->getDirs().size());
+      for(const auto dd : m_groupDef->getDirs())
       {
-        TemplateList *exampleList = TemplateList::alloc();
-        for (const auto &ex : m_groupDef->getExamples())
-        {
-          exampleList->append(PageContext::alloc(ex,FALSE,TRUE));
-        }
-        cache.examples.reset(exampleList);
+        list.push_back(DirContext::alloc(dd));
       }
-      return cache.examples.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant pages() const
+    TemplateVariant createFiles() const
     {
-      Cachable &cache = getCache();
-      if (!cache.pages)
+      TemplateVariantList list;
+      list.reserve(m_groupDef->getFiles().size());
+      for (const auto &fd : m_groupDef->getFiles())
       {
-        TemplateList *pageList = TemplateList::alloc();
-        for (const auto &ex : m_groupDef->getPages())
-        {
-          pageList->append(PageContext::alloc(ex,FALSE,TRUE));
-        }
-        cache.pages.reset(pageList);
+        list.push_back(FileContext::alloc(fd));
       }
-      return cache.pages.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant dirs() const
+    TemplateVariant createClasses() const
     {
-      Cachable &cache = getCache();
-      if (!cache.dirs)
+      TemplateVariantList list;
+      list.reserve(m_groupDef->getClasses().size());
+      for (const auto &cd : m_groupDef->getClasses())
       {
-        TemplateList *dirList = TemplateList::alloc();
-        for(const auto dd : m_groupDef->getDirs())
+        if (cd->visibleInParentsDeclList())
         {
-          dirList->append(DirContext::alloc(dd));
+          list.push_back(ClassContext::alloc(cd));
         }
-        cache.dirs.reset(dirList);
       }
-      return cache.dirs.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant files() const
+    TemplateVariant createNamespaces() const
     {
-      Cachable &cache = getCache();
-      if (!cache.files)
+      TemplateVariantList list;
+      list.reserve(m_groupDef->getNamespaces().size());
+      for (const auto &nd : m_groupDef->getNamespaces())
       {
-        TemplateList *fileList = TemplateList::alloc();
-        for (const auto &fd : m_groupDef->getFiles())
+        if (nd->isLinkable() && !nd->isConstantGroup())
         {
-          fileList->append(FileContext::alloc(fd));
+          list.push_back(NamespaceContext::alloc(nd));
         }
-        cache.files.reset(fileList);
       }
-      return cache.files.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant classes() const
+    TemplateVariant createConstantgroups() const
     {
-      Cachable &cache = getCache();
-      if (!cache.classes)
+      TemplateVariantList list;
+      list.reserve(m_groupDef->getNamespaces().size());
+      for (const auto &nd : m_groupDef->getNamespaces())
       {
-        TemplateList *classList = TemplateList::alloc();
-        for (const auto &cd : m_groupDef->getClasses())
+        if (nd->isLinkable() && nd->isConstantGroup())
         {
-          if (cd->visibleInParentsDeclList())
-          {
-            classList->append(ClassContext::alloc(cd));
-          }
+          list.push_back(NamespaceContext::alloc(nd));
         }
-        cache.classes.reset(classList);
       }
-      return cache.classes.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant namespaces() const
+    TemplateVariant createExamples() const
     {
-      Cachable &cache = getCache();
-      if (!cache.namespaces)
+      TemplateVariantList list;
+      list.reserve(m_groupDef->getExamples().size());
+      for (const auto &ex : m_groupDef->getExamples())
       {
-        TemplateList *namespaceList = TemplateList::alloc();
-        for (const auto &nd : m_groupDef->getNamespaces())
-        {
-          if (nd->isLinkable() && !nd->isConstantGroup())
-          {
-            namespaceList->append(NamespaceContext::alloc(nd));
-          }
-        }
-        cache.namespaces.reset(namespaceList);
+        list.push_back(PageContext::alloc(ex,FALSE,TRUE));
       }
-      return cache.namespaces.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant constantgroups() const
+    TemplateVariant createPages() const
     {
-      Cachable &cache = getCache();
-      if (!cache.constantgroups)
+      TemplateVariantList list;
+      list.reserve(m_groupDef->getPages().size());
+      for (const auto &ex : m_groupDef->getPages())
       {
-        TemplateList *namespaceList = TemplateList::alloc();
-        for (const auto &nd : m_groupDef->getNamespaces())
-        {
-          if (nd->isLinkable() && nd->isConstantGroup())
-          {
-            namespaceList->append(NamespaceContext::alloc(nd));
-          }
-        }
-        cache.constantgroups.reset(namespaceList);
+        list.push_back(PageContext::alloc(ex,FALSE,TRUE));
       }
-      return cache.constantgroups.get();
+      return TemplateImmutableList::alloc(list);
     }
-
-    TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list,
-                                  MemberListType type,const QCString &title,bool=FALSE) const
+    TemplateVariant createMemberList(MemberListType type,const QCString &title) const
     {
-      if (!list)
-      {
-        MemberList *ml = m_groupDef->getMemberList(type);
-        if (ml)
-        {
-          list.reset(MemberListInfoContext::alloc(m_groupDef,relPathAsString(),ml,title,""));
-        }
-      }
-      if (list)
-      {
-        return list.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
+      const MemberList *ml = m_groupDef->getMemberList(type);
+      return ml ? TemplateVariant(MemberListInfoContext::alloc(m_groupDef,relPathAsString(),ml,title,""))
+                : TemplateVariant(false);
     }
-    TemplateVariant macros() const
+    TemplateVariant createMacros() const
     {
-      return getMemberList(getCache().macros,MemberListType_decDefineMembers,theTranslator->trDefines());
+      return createMemberList(MemberListType_decDefineMembers,theTranslator->trDefines());
     }
-    TemplateVariant typedefs() const
+    TemplateVariant createTypedefs() const
     {
-      return getMemberList(getCache().typedefs,MemberListType_decTypedefMembers,theTranslator->trTypedefs());
+      return createMemberList(MemberListType_decTypedefMembers,theTranslator->trTypedefs());
     }
-    TemplateVariant enums() const
+    TemplateVariant createEnums() const
     {
-      return getMemberList(getCache().enums,MemberListType_decEnumMembers,theTranslator->trEnumerations());
+      return createMemberList(MemberListType_decEnumMembers,theTranslator->trEnumerations());
     }
-    TemplateVariant enumValues() const
+    TemplateVariant createEnumValues() const
     {
-      return getMemberList(getCache().enums,MemberListType_decEnumValMembers,theTranslator->trEnumerationValues());
+      return createMemberList(MemberListType_decEnumValMembers,theTranslator->trEnumerationValues());
     }
-    TemplateVariant functions() const
+    TemplateVariant createFunctions() const
     {
-      QCString title = theTranslator->trFunctions();
       SrcLangExt lang = m_groupDef->getLanguage();
-      if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprograms();
-      else if (lang==SrcLangExt_VHDL) title=theTranslator->trFunctionAndProc();
-      return getMemberList(getCache().functions,MemberListType_decFuncMembers,title);
+      return createMemberList(MemberListType_decFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprograms() :
+                                                             lang==SrcLangExt_VHDL    ? theTranslator->trFunctionAndProc() :
+                                                                                        theTranslator->trFunctions());
     }
-    TemplateVariant variables() const
+    TemplateVariant createVariables() const
     {
       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
-      return getMemberList(getCache().variables,MemberListType_decVarMembers,
-                           sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables());
-    }
-    TemplateVariant signals() const
-    {
-      return getMemberList(getCache().signals,MemberListType_signals,theTranslator->trSignals());
+      return createMemberList(MemberListType_decVarMembers, sliceOpt ? theTranslator->trConstants() :
+                                                                       theTranslator->trVariables());
     }
-    TemplateVariant publicSlots() const
+    TemplateVariant createSignals() const
     {
-      return getMemberList(getCache().publicSlots,MemberListType_pubSlots,theTranslator->trPublicSlots());
+      return createMemberList(MemberListType_signals,theTranslator->trSignals());
     }
-    TemplateVariant protectedSlots() const
+    TemplateVariant createPublicSlots() const
     {
-      return getMemberList(getCache().protectedSlots,MemberListType_proSlots,theTranslator->trProtectedSlots());
+      return createMemberList(MemberListType_pubSlots,theTranslator->trPublicSlots());
     }
-    TemplateVariant privateSlots() const
+    TemplateVariant createProtectedSlots() const
     {
-      return getMemberList(getCache().privateSlots,MemberListType_priSlots,theTranslator->trPrivateSlots());
+      return createMemberList(MemberListType_proSlots,theTranslator->trProtectedSlots());
     }
-    TemplateVariant events() const
+    TemplateVariant createPrivateSlots() const
     {
-      return getMemberList(getCache().events,MemberListType_events,theTranslator->trEvents());
+      return createMemberList(MemberListType_priSlots,theTranslator->trPrivateSlots());
     }
-    TemplateVariant properties() const
+    TemplateVariant createEvents() const
     {
-      return getMemberList(getCache().properties,MemberListType_properties,theTranslator->trProperties());
+      return createMemberList(MemberListType_events,theTranslator->trEvents());
     }
-    TemplateVariant friends() const
+    TemplateVariant createProperties() const
     {
-      return getMemberList(getCache().friends,MemberListType_friends,theTranslator->trFriends());
+      return createMemberList(MemberListType_properties,theTranslator->trProperties());
     }
-    TemplateVariant memberGroups() const
+    TemplateVariant createFriends() const
     {
-      Cachable &cache = getCache();
-      if (!cache.memberGroups)
-      {
-        if (!m_groupDef->getMemberGroups().empty())
-        {
-          cache.memberGroups.reset(MemberGroupListContext::alloc(m_groupDef,relPathAsString(),m_groupDef->getMemberGroups(),m_groupDef->subGrouping()));
-        }
-        else
-        {
-          cache.memberGroups.reset(MemberGroupListContext::alloc());
-        }
-      }
-      return cache.memberGroups.get();
+      return createMemberList(MemberListType_friends,theTranslator->trFriends());
     }
-    TemplateVariant detailedMacros() const
+    TemplateVariant createDetailedMacros() const
     {
-      return getMemberList(getCache().detailedMacros,MemberListType_docDefineMembers,theTranslator->trDefineDocumentation());
+      return createMemberList(MemberListType_docDefineMembers,theTranslator->trDefineDocumentation());
     }
-    TemplateVariant detailedTypedefs() const
+    TemplateVariant createDetailedTypedefs() const
     {
-      return getMemberList(getCache().detailedTypedefs,MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
+      return createMemberList(MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
     }
-    TemplateVariant detailedEnums() const
+    TemplateVariant createDetailedEnums() const
     {
-      return getMemberList(getCache().detailedEnums,MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
+      return createMemberList(MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
     }
-    TemplateVariant detailedEnumValues() const
+    TemplateVariant createDetailedEnumValues() const
     {
-      return getMemberList(getCache().detailedEnumValues,MemberListType_docEnumValMembers,theTranslator->trEnumerationValueDocumentation());
+      return createMemberList(MemberListType_docEnumValMembers,theTranslator->trEnumerationValueDocumentation());
     }
-    TemplateVariant detailedFunctions() const
+    TemplateVariant createDetailedFunctions() const
     {
-      QCString title = theTranslator->trFunctionDocumentation();
       SrcLangExt lang = m_groupDef->getLanguage();
-      if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprogramDocumentation();
-      return getMemberList(getCache().detailedFunctions,MemberListType_docFuncMembers,title);
+      return createMemberList(MemberListType_docFuncMembers, lang==SrcLangExt_Fortran ? theTranslator->trSubprogramDocumentation() :
+                                                                                        theTranslator->trFunctionDocumentation());
     }
-    TemplateVariant detailedVariables() const
+    TemplateVariant createDetailedVariables() const
     {
-      return getMemberList(getCache().detailedVariables,MemberListType_docVarMembers,theTranslator->trVariableDocumentation());
+      return createMemberList(MemberListType_docVarMembers,theTranslator->trVariableDocumentation());
     }
-    TemplateVariant detailedSignals() const
+    TemplateVariant createDetailedSignals() const
     {
-      return getMemberList(getCache().detailedSignals,MemberListType_docSignalMembers,theTranslator->trSignals());
+      return createMemberList(MemberListType_docSignalMembers,theTranslator->trSignals());
     }
-    TemplateVariant detailedPublicSlots() const
+    TemplateVariant createDetailedPublicSlots() const
     {
-      return getMemberList(getCache().detailedPublicSlots,MemberListType_docPubSlotMembers,theTranslator->trPublicSlots());
+      return createMemberList(MemberListType_docPubSlotMembers,theTranslator->trPublicSlots());
     }
-    TemplateVariant detailedProtectedSlots() const
+    TemplateVariant createDetailedProtectedSlots() const
     {
-      return getMemberList(getCache().detailedProtectedSlots,MemberListType_docProSlotMembers,theTranslator->trProtectedSlots());
+      return createMemberList(MemberListType_docProSlotMembers,theTranslator->trProtectedSlots());
     }
-    TemplateVariant detailedPrivateSlots() const
+    TemplateVariant createDetailedPrivateSlots() const
     {
-      return getMemberList(getCache().detailedPrivateSlots,MemberListType_docPriSlotMembers,theTranslator->trPrivateSlots());
+      return createMemberList(MemberListType_docPriSlotMembers,theTranslator->trPrivateSlots());
     }
-    TemplateVariant detailedEvents() const
+    TemplateVariant createDetailedEvents() const
     {
-      return getMemberList(getCache().detailedEvents,MemberListType_docEventMembers,theTranslator->trEventDocumentation(),TRUE);
+      return createMemberList(MemberListType_docEventMembers,theTranslator->trEventDocumentation());
     }
-    TemplateVariant detailedProperties() const
+    TemplateVariant createDetailedProperties() const
     {
-      return getMemberList(getCache().detailedProperties,MemberListType_docPropMembers,theTranslator->trPropertyDocumentation(),TRUE);
+      return createMemberList(MemberListType_docPropMembers,theTranslator->trPropertyDocumentation());
     }
-    TemplateVariant detailedFriends() const
+    TemplateVariant createDetailedFriends() const
     {
-      return getMemberList(getCache().detailedFriends,MemberListType_docFriendMembers,theTranslator->trFriends(),TRUE);
+      return createMemberList(MemberListType_docFriendMembers,theTranslator->trFriends());
     }
-    TemplateVariant inlineClasses() const
+    TemplateVariant createInlineClasses() const
     {
-      Cachable &cache = getCache();
-      if (!cache.inlineClasses)
+      TemplateVariantList list;
+      for (const auto &cd : m_groupDef->getClasses())
       {
-        TemplateList *classList = TemplateList::alloc();
-        for (const auto &cd : m_groupDef->getClasses())
+        if (!cd->isAnonymous() &&
+            cd->isLinkableInProject() &&
+            cd->isEmbeddedInOuterScope() &&
+            cd->partOfGroups().empty())
         {
-          if (!cd->isAnonymous() &&
-              cd->isLinkableInProject() &&
-              cd->isEmbeddedInOuterScope() &&
-              cd->partOfGroups().empty())
-          {
-            classList->append(ClassContext::alloc(cd));
-          }
+          list.push_back(ClassContext::alloc(cd));
         }
-        cache.inlineClasses.reset(classList);
       }
-      return cache.inlineClasses.get();
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant compoundType() const
+    TemplateVariant createMemberGroups() const
     {
-      return "module"; //theTranslator->trGroup(FALSE,TRUE);
+      return !m_groupDef->getMemberGroups().empty() ?
+          MemberGroupListContext::alloc(m_groupDef,relPathAsString(),m_groupDef->getMemberGroups(),m_groupDef->subGrouping()) :
+          MemberGroupListContext::alloc();
     }
-  private:
+    DotGroupCollaborationPtr createGroupGraph() const
+    {
+      return std::make_shared<DotGroupCollaboration>(m_groupDef);
+    }
+
     const GroupDef *m_groupDef;
     struct Cachable : public DefinitionContext<ModuleContext::Private>::Cachable
     {
-      Cachable(const GroupDef *gd) : DefinitionContext<ModuleContext::Private>::Cachable(gd) {}
-      SharedPtr<TemplateList>               modules;
-      SharedPtr<TemplateList>               dirs;
-      SharedPtr<TemplateList>               files;
-      SharedPtr<TemplateList>               classes;
-      SharedPtr<TemplateList>               namespaces;
-      SharedPtr<TemplateList>               constantgroups;
-      SharedPtr<TemplateList>               examples;
-      SharedPtr<TemplateList>               pages;
-      SharedPtr<MemberListInfoContext>      macros;
-      SharedPtr<MemberListInfoContext>      typedefs;
-      SharedPtr<MemberListInfoContext>      enums;
-      SharedPtr<MemberListInfoContext>      enumValues;
-      SharedPtr<MemberListInfoContext>      functions;
-      SharedPtr<MemberListInfoContext>      variables;
-      SharedPtr<MemberListInfoContext>      signals;
-      SharedPtr<MemberListInfoContext>      publicSlots;
-      SharedPtr<MemberListInfoContext>      protectedSlots;
-      SharedPtr<MemberListInfoContext>      privateSlots;
-      SharedPtr<MemberListInfoContext>      events;
-      SharedPtr<MemberListInfoContext>      properties;
-      SharedPtr<MemberListInfoContext>      friends;
-      SharedPtr<MemberGroupListContext>     memberGroups;
-      SharedPtr<MemberListInfoContext>      detailedMacros;
-      SharedPtr<MemberListInfoContext>      detailedTypedefs;
-      SharedPtr<MemberListInfoContext>      detailedEnums;
-      SharedPtr<MemberListInfoContext>      detailedEnumValues;
-      SharedPtr<MemberListInfoContext>      detailedFunctions;
-      SharedPtr<MemberListInfoContext>      detailedVariables;
-      SharedPtr<MemberListInfoContext>      detailedSignals;
-      SharedPtr<MemberListInfoContext>      detailedPublicSlots;
-      SharedPtr<MemberListInfoContext>      detailedProtectedSlots;
-      SharedPtr<MemberListInfoContext>      detailedPrivateSlots;
-      SharedPtr<MemberListInfoContext>      detailedEvents;
-      SharedPtr<MemberListInfoContext>      detailedProperties;
-      SharedPtr<MemberListInfoContext>      detailedFriends;
-      SharedPtr<TemplateList>               inlineClasses;
-      std::unique_ptr<DotGroupCollaboration>      groupGraph;
+      CachedItem<TemplateVariant,  Private, &Private::createModules>                modules;
+      CachedItem<TemplateVariant,  Private, &Private::createDirs>                   dirs;
+      CachedItem<TemplateVariant,  Private, &Private::createFiles>                  files;
+      CachedItem<TemplateVariant,  Private, &Private::createClasses>                classes;
+      CachedItem<TemplateVariant,  Private, &Private::createNamespaces>             namespaces;
+      CachedItem<TemplateVariant,  Private, &Private::createConstantgroups>         constantgroups;
+      CachedItem<TemplateVariant,  Private, &Private::createExamples>               examples;
+      CachedItem<TemplateVariant,  Private, &Private::createPages>                  pages;
+      CachedItem<TemplateVariant,  Private, &Private::createMacros>                 macros;
+      CachedItem<TemplateVariant,  Private, &Private::createTypedefs>               typedefs;
+      CachedItem<TemplateVariant,  Private, &Private::createEnums>                  enums;
+      CachedItem<TemplateVariant,  Private, &Private::createEnumValues>             enumValues;
+      CachedItem<TemplateVariant,  Private, &Private::createFunctions>              functions;
+      CachedItem<TemplateVariant,  Private, &Private::createVariables>              variables;
+      CachedItem<TemplateVariant,  Private, &Private::createSignals>                signals;
+      CachedItem<TemplateVariant,  Private, &Private::createPublicSlots>            publicSlots;
+      CachedItem<TemplateVariant,  Private, &Private::createProtectedSlots>         protectedSlots;
+      CachedItem<TemplateVariant,  Private, &Private::createPrivateSlots>           privateSlots;
+      CachedItem<TemplateVariant,  Private, &Private::createEvents>                 events;
+      CachedItem<TemplateVariant,  Private, &Private::createProperties>             properties;
+      CachedItem<TemplateVariant,  Private, &Private::createFriends>                friends;
+      CachedItem<TemplateVariant,  Private, &Private::createMemberGroups>           memberGroups;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedMacros>         detailedMacros;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedTypedefs>       detailedTypedefs;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedEnums>          detailedEnums;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedEnumValues>     detailedEnumValues;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedFunctions>      detailedFunctions;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedVariables>      detailedVariables;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedSignals>        detailedSignals;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedPublicSlots>    detailedPublicSlots;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedProtectedSlots> detailedProtectedSlots;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedPrivateSlots>   detailedPrivateSlots;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedEvents>         detailedEvents;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedProperties>     detailedProperties;
+      CachedItem<TemplateVariant,  Private, &Private::createDetailedFriends>        detailedFriends;
+      CachedItem<TemplateVariant,  Private, &Private::createInlineClasses>          inlineClasses;
+      CachedItem<DotGroupCollaborationPtr, Private, &Private::createGroupGraph>     groupGraph;
     };
-    Cachable &getCache() const
-    {
-      Cachable *c = static_cast<Cachable*>(m_groupDef->cookie());
-      assert(c!=0);
-      return *c;
-    }
-    static PropertyMapper<ModuleContext::Private> s_inst;
+    Cachable m_cachable;
+    static const PropertyMap<ModuleContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<ModuleContext::Private> ModuleContext::Private::s_inst;
+//%% struct Module(Symbol): group information
+//%% {
+const PropertyMap<ModuleContext::Private> ModuleContext::Private::s_inst {
+  BASE_PROPERTIES,
+  {  "title",                     &Private::title },
+  {  "highlight",                 &Private::highlight },
+  {  "subhighlight",              &Private::subHighlight },
+  {  "hasGroupGraph",             &Private::hasGroupGraph },
+  {  "groupGraph",                &Private::groupGraph },
+  {  "hasDetails",                &Private::hasDetails },
+  {  "modules",                   &Private::modules },
+  {  "dirs",                      &Private::dirs },
+  {  "files",                     &Private::files },
+  {  "namespaces",                &Private::namespaces },
+  {  "classes",                   &Private::classes },
+  {  "constantgroups",            &Private::constantgroups },
+  {  "examples",                  &Private::examples },
+  {  "macros",                    &Private::macros },
+  {  "typedefs",                  &Private::typedefs },
+  {  "enums",                     &Private::enums },
+  {  "enumvalues",                &Private::enumValues },
+  {  "functions",                 &Private::functions },
+  {  "variables",                 &Private::variables },
+  {  "signals",                   &Private::signals },
+  {  "publicSlots",               &Private::publicSlots },
+  {  "protectedSlots",            &Private::protectedSlots },
+  {  "privateSlots",              &Private::privateSlots },
+  {  "events",                    &Private::events },
+  {  "properties",                &Private::properties },
+  {  "friends",                   &Private::friends },
+  {  "memberGroups",              &Private::memberGroups },
+  {  "detailedMacros",            &Private::detailedMacros },
+  {  "detailedTypedefs",          &Private::detailedTypedefs },
+  {  "detailedEnums",             &Private::detailedEnums },
+  {  "detailedEnumValues",        &Private::detailedEnumValues },
+  {  "detailedFunctions",         &Private::detailedFunctions },
+  {  "detailedVariables",         &Private::detailedVariables },
+  {  "detailedSignals",           &Private::detailedSignals },
+  {  "detailedPublicSlots",       &Private::detailedPublicSlots },
+  {  "detailedProtectedSlots",    &Private::detailedProtectedSlots },
+  {  "detailedPrivateSlots",      &Private::detailedPrivateSlots },
+  {  "detailedEvents",            &Private::detailedEvents },
+  {  "detailedProperties",        &Private::detailedProperties },
+  {  "detailedFriends",           &Private::detailedFriends },
+  {  "inlineClasses",             &Private::inlineClasses },
+  {  "compoundType",              &Private::compoundType }
+};
+//%% }
 
-ModuleContext::ModuleContext(const GroupDef *gd) : RefCountedContext("ModuleContext")
+ModuleContext::ModuleContext(const GroupDef *gd) : p(std::make_unique<Private>(gd))
 {
-  p = new Private(gd);
 }
 
 ModuleContext::~ModuleContext()
 {
-  delete p;
 }
 
 TemplateVariant ModuleContext::get(const QCString &n) const
@@ -6008,16 +5018,14 @@ class ClassListContext::Private : public GenericNodeListContext
     }
 };
 
-ClassListContext::ClassListContext() : RefCountedContext("ClassListContext")
+ClassListContext::ClassListContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
   p->addClasses(*Doxygen::classLinkedMap);
   p->addClasses(*Doxygen::hiddenClassLinkedMap);
 }
 
 ClassListContext::~ClassListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -6031,118 +5039,80 @@ TemplateVariant ClassListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *ClassListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr ClassListContext::createIterator() const
 {
   return p->createIterator();
 }
 
 //------------------------------------------------------------------------
 
-//%% list ClassIndex[Class] : list of classes
 class ClassIndexContext::Private
 {
   public:
-    Private()
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("list",        &Private::list);
-        s_inst.addProperty("fileName",    &Private::fileName);
-        s_inst.addProperty("relPath",     &Private::relPath);
-        s_inst.addProperty("highlight",   &Private::highlight);
-        s_inst.addProperty("subhighlight",&Private::subhighlight);
-        s_inst.addProperty("title",       &Private::title);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant list() const
-    {
-      if (!m_cache.classes)
-      {
-        TemplateList *classList = TemplateList::alloc();
-        if (Doxygen::classLinkedMap)
-        {
-          for (const auto &cd : *Doxygen::classLinkedMap)
-          {
-            if (cd->getLanguage()==SrcLangExt_VHDL &&
-                ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS ||
-                 (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
-               ) // no architecture
-            {
-              continue;
-            }
-            if (cd->isLinkableInProject() && cd->templateMaster()==0)
-            {
-              classList->append(ClassContext::alloc(cd.get()));
-            }
-          }
-        }
-        m_cache.classes.reset(classList);
-      }
-      return m_cache.classes.get();
-    }
-    TemplateVariant fileName() const
-    {
-      return "classes";
-    }
-    TemplateVariant relPath() const
-    {
-      return "";
-    }
-    TemplateVariant highlight() const
-    {
-      return "classes";
-    }
-    TemplateVariant subhighlight() const
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant list() const                 { return m_classes.get(this); }
+    TemplateVariant fileName() const             { return "classes"; }
+    TemplateVariant relPath() const              { return ""; }
+    TemplateVariant highlight() const            { return "classes"; }
+    TemplateVariant subhighlight() const         { return "classindex"; }
+    TemplateVariant title() const
     {
-      return "classindex";
+      return Config_getBool(OPTIMIZE_FOR_FORTRAN) ? theTranslator->trDataTypes()   :
+             Config_getBool(OPTIMIZE_OUTPUT_VHDL) ? theTranslator->trDesignUnits() :
+                                                    theTranslator->trCompoundIndex();
     }
-    TemplateVariant title() const
+  private:
+    TemplateVariant createClasses() const
     {
-      static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
-      static bool vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
-      if (fortranOpt)
-      {
-        return theTranslator->trDataTypes();
-      }
-      else if (vhdlOpt)
-      {
-        return theTranslator->trDesignUnits();
-      }
-      else
+      TemplateVariantList list;
+      list.reserve(Doxygen::classLinkedMap->size());
+      if (Doxygen::classLinkedMap)
       {
-        return theTranslator->trCompoundIndex();
+        for (const auto &cd : *Doxygen::classLinkedMap)
+        {
+          if (cd->getLanguage()==SrcLangExt_VHDL &&
+              ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS ||
+               (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
+             ) // no architecture
+          {
+            continue;
+          }
+          if (cd->isLinkableInProject() && cd->templateMaster()==0)
+          {
+            list.push_back(ClassContext::alloc(cd.get()));
+          }
+        }
       }
+      return TemplateImmutableList::alloc(list);
     }
-  private:
-    struct Cachable
-    {
-      SharedPtr<TemplateList> classes;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<ClassIndexContext::Private> s_inst;
+
+    CachedItem<TemplateVariant,  Private, &Private::createClasses> m_classes;
+    static const PropertyMap<ClassIndexContext::Private> s_inst;
 };
 
-PropertyMapper<ClassIndexContext::Private> ClassIndexContext::Private::s_inst;
+//%% struct ClassIndex
+//%% {
+const PropertyMap<ClassIndexContext::Private> ClassIndexContext::Private::s_inst {
+  {  "list",        &Private::list },
+  {  "fileName",    &Private::fileName },
+  {  "relPath",     &Private::relPath },
+  {  "highlight",   &Private::highlight },
+  {  "subhighlight",&Private::subhighlight },
+  {  "title",       &Private::title }
+};
+//%% }
 
-ClassIndexContext::ClassIndexContext() : RefCountedContext("ClassIndexContext")
+ClassIndexContext::ClassIndexContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
-  //p->addClasses(*Doxygen::hiddenClasses);
 }
 
 ClassIndexContext::~ClassIndexContext()
 {
-  delete p;
 }
 
 // TemplateStructIntf
@@ -6158,26 +5128,25 @@ StringVector ClassIndexContext::fields() const
 
 //------------------------------------------------------------------------
 
-static int computeMaxDepth(const TemplateListIntf *list)
+static int computeMaxDepth(const TemplateListIntfPtr list)
 {
   int maxDepth=0;
   if (list)
   {
-    TemplateListIntf::ConstIterator *it = list->createIterator();
+    TemplateListIntf::ConstIteratorPtr it = list->createIterator();
     TemplateVariant v;
     for (it->toFirst();it->current(v);it->toNext())
     {
-      const TemplateStructIntf *s = v.toStruct();
+      const TemplateStructIntfPtr s = v.toStruct();
       TemplateVariant child = s->get("children");
       int d = computeMaxDepth(child.toList())+1;
       if (d>maxDepth) maxDepth=d;
     }
-    delete it;
   }
   return maxDepth;
 }
 
-static int computeNumNodesAtLevel(const TemplateStructIntf *s,int level,int maxLevel)
+static int computeNumNodesAtLevel(const TemplateStructIntfPtr s,int level,int maxLevel)
 {
   int num=0;
   if (level<maxLevel)
@@ -6186,19 +5155,18 @@ static int computeNumNodesAtLevel(const TemplateStructIntf *s,int level,int maxL
     TemplateVariant child = s->get("children");
     if (child.toList())
     {
-      TemplateListIntf::ConstIterator *it = child.toList()->createIterator();
+      TemplateListIntf::ConstIteratorPtr it = child.toList()->createIterator();
       TemplateVariant v;
       for (it->toFirst();it->current(v);it->toNext())
       {
         num+=computeNumNodesAtLevel(v.toStruct(),level+1,maxLevel);
       }
-      delete it;
     }
   }
   return num;
 }
 
-static int computePreferredDepth(const TemplateListIntf *list,int maxDepth)
+static int computePreferredDepth(const TemplateListIntfPtr list,int maxDepth)
 {
   int preferredNumEntries = Config_getInt(HTML_INDEX_NUM_ENTRIES);
   int preferredDepth=1;
@@ -6208,13 +5176,12 @@ static int computePreferredDepth(const TemplateListIntf *list,int maxDepth)
     for (int i=1;i<=depth;i++)
     {
       int num=0;
-      TemplateListIntf::ConstIterator *it = list->createIterator();
+      TemplateListIntf::ConstIteratorPtr it = list->createIterator();
       TemplateVariant v;
       for (it->toFirst();it->current(v);it->toNext())
       {
         num+=computeNumNodesAtLevel(v.toStruct(),0,i);
       }
-      delete it;
       if (num<=preferredNumEntries)
       {
         preferredDepth=i;
@@ -6230,142 +5197,87 @@ static int computePreferredDepth(const TemplateListIntf *list,int maxDepth)
 
 //------------------------------------------------------------------------
 
-//%% struct ClassHierarchy: inheritance tree
-//%% {
 class ClassHierarchyContext::Private
 {
   public:
     Private()
     {
-      m_classTree.reset(NestingContext::alloc(0,ContextTreeType::ClassInheritance,0));
+      m_classTree = NestingContext::alloc(0,ContextTreeType::ClassInheritance,0);
+      auto ctx = std::dynamic_pointer_cast<NestingContext>(m_classTree);
       ClassDefSet visitedClasses;
-      m_classTree->addClassHierarchy(*Doxygen::classLinkedMap,visitedClasses);
-      m_classTree->addClassHierarchy(*Doxygen::hiddenClassLinkedMap,visitedClasses);
-      //%% ClassInheritance tree
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("tree",            &Private::tree);
-        s_inst.addProperty("fileName",        &Private::fileName);
-        s_inst.addProperty("relPath",         &Private::relPath);
-        s_inst.addProperty("highlight",       &Private::highlight);
-        s_inst.addProperty("subhighlight",    &Private::subhighlight);
-        s_inst.addProperty("title",           &Private::title);
-        s_inst.addProperty("preferredDepth",  &Private::preferredDepth);
-        s_inst.addProperty("maxDepth",        &Private::maxDepth);
-        s_inst.addProperty("diagrams",        &Private::diagrams);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant tree() const
-    {
-      return m_classTree.get();
-    }
-    TemplateVariant fileName() const
-    {
-      return "hierarchy";
-    }
-    TemplateVariant relPath() const
-    {
-      return "";
-    }
-    TemplateVariant highlight() const
-    {
-      return "classes";
-    }
-    TemplateVariant subhighlight() const
-    {
-      return "classhierarchy";
-    }
-    DotGfxHierarchyTable *getHierarchy() const
-    {
-      if (!m_cache.hierarchy)
-      {
-        m_cache.hierarchy.reset(new DotGfxHierarchyTable());
-      }
-      return m_cache.hierarchy.get();
+      ctx->addClassHierarchy(*Doxygen::classLinkedMap,visitedClasses);
+      ctx->addClassHierarchy(*Doxygen::hiddenClassLinkedMap,visitedClasses);
     }
-    TemplateVariant diagrams() const
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant tree() const                 { return TemplateVariant(m_classTree); }
+    TemplateVariant fileName() const             { return "hierarchy"; }
+    TemplateVariant relPath() const              { return ""; }
+    TemplateVariant highlight() const            { return "classes"; }
+    TemplateVariant subhighlight() const         { return "classhierarchy"; }
+    TemplateVariant diagrams() const             { return m_diagrams.get(this); }
+    TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
+    TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
+    TemplateVariant title() const
     {
-      if (!m_cache.diagrams)
-      {
-        TemplateList *diagrams = TemplateList::alloc();
-        DotGfxHierarchyTable *hierarchy = getHierarchy();
-        int id=0;
-        for (auto n : hierarchy->subGraphs())
-        {
-          diagrams->append(InheritanceGraphContext::alloc(hierarchy,n,id++));
-        }
-        m_cache.diagrams.reset(diagrams);
-      }
-      return m_cache.diagrams.get();
+      return Config_getBool(OPTIMIZE_OUTPUT_VHDL) ? theTranslator->trDesignUnitHierarchy() :
+                                                    theTranslator->trClassHierarchy();
     }
-    TemplateVariant title() const
+  private:
+    int createMaxDepth() const
     {
-      static bool vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
-      if (vhdlOpt)
-      {
-        return theTranslator->trDesignUnitHierarchy();
-      }
-      else
-      {
-        return theTranslator->trClassHierarchy();
-      }
+      return computeMaxDepth(m_classTree);
     }
-    TemplateVariant maxDepth() const
+    int createPreferredDepth() const
     {
-      if (!m_cache.maxDepthComputed)
-      {
-        m_cache.maxDepth = computeMaxDepth(m_classTree.get());
-        m_cache.maxDepthComputed=TRUE;
-      }
-      return m_cache.maxDepth;
+      return computePreferredDepth(m_classTree,m_maxDepth.get(this));
     }
-    TemplateVariant preferredDepth() const
+    TemplateVariant createDiagrams() const
     {
-      if (!m_cache.preferredDepthComputed)
+      TemplateVariantList diagrams;
+      DotGfxHierarchyTablePtr hierarchy = std::make_shared<DotGfxHierarchyTable>();
+      diagrams.reserve(hierarchy->subGraphs().size());
+      int id=0;
+      for (auto n : hierarchy->subGraphs())
       {
-        m_cache.preferredDepth = computePreferredDepth(m_classTree.get(),maxDepth().toInt());
-        m_cache.preferredDepthComputed=TRUE;
+        diagrams.push_back(InheritanceGraphContext::alloc(hierarchy,n,id++));
       }
-      return m_cache.preferredDepth;
+      return TemplateImmutableList::alloc(diagrams);
     }
-  private:
-    SharedPtr<NestingContext> m_classTree;
-    struct Cachable
-    {
-      Cachable() : maxDepth(0), maxDepthComputed(FALSE),
-                   preferredDepth(0), preferredDepthComputed(FALSE) {}
-      int   maxDepth;
-      bool  maxDepthComputed;
-      int   preferredDepth;
-      bool  preferredDepthComputed;
-      SharedPtr<TemplateList> diagrams;
-      std::unique_ptr<DotGfxHierarchyTable> hierarchy;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<ClassHierarchyContext::Private> s_inst;
+
+    TemplateListIntfPtr m_classTree;
+    CachedItem<int,                     Private, &Private::createMaxDepth>       m_maxDepth;
+    CachedItem<int,                     Private, &Private::createPreferredDepth> m_preferredDepth;
+    CachedItem<TemplateVariant,         Private, &Private::createDiagrams>       m_diagrams;
+    static const PropertyMap<ClassHierarchyContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<ClassHierarchyContext::Private> ClassHierarchyContext::Private::s_inst;
+//%% struct ClassHierarchy: inheritance tree
+//%% {
+const PropertyMap<ClassHierarchyContext::Private> ClassHierarchyContext::Private::s_inst {
+  {  "tree",            &Private::tree },
+  {  "fileName",        &Private::fileName },
+  {  "relPath",         &Private::relPath },
+  {  "highlight",       &Private::highlight },
+  {  "subhighlight",    &Private::subhighlight },
+  {  "diagrams",        &Private::diagrams },
+  {  "maxDepth",        &Private::maxDepth },
+  {  "preferredDepth",  &Private::preferredDepth },
+  {  "title",           &Private::title },
+};
+//%% }
 
-ClassHierarchyContext::ClassHierarchyContext() : RefCountedContext("ClassHierarchyContext")
+ClassHierarchyContext::ClassHierarchyContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 ClassHierarchyContext::~ClassHierarchyContext()
 {
-  delete p;
 }
 
 TemplateVariant ClassHierarchyContext::get(const QCString &name) const
@@ -6380,8 +5292,6 @@ StringVector ClassHierarchyContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct NestingNode: node is a nesting relation tree
-//%% {
 class NestingNodeContext::Private
 {
   public:
@@ -6392,49 +5302,8 @@ class NestingNodeContext::Private
         ClassDefSet &visitedClasses)
       : m_parent(parent), m_type(type), m_def(d), m_level(level), m_index(index)
     {
-      m_children.reset(NestingContext::alloc(thisNode,m_type,level+1));
-      m_members.reset(NestingContext::alloc(thisNode,m_type,level+1));
-      static bool init=FALSE;
-      if (!init)
-      {
-        //%% bool is_leaf_node: true if this node does not have any children
-        s_inst.addProperty("is_leaf_node",&Private::isLeafNode);
-        //%% Nesting children: list of nested classes/namespaces
-        s_inst.addProperty("children",&Private::children);
-        //%% Nesting children: list of nested classes/namespaces
-        s_inst.addProperty("members",&Private::members);
-        //%% [optional] Class class: class info (if this node represents a class)
-        s_inst.addProperty("class",&Private::getClass);
-        //%% [optional] Namespace namespace: namespace info (if this node represents a namespace)
-        s_inst.addProperty("namespace",&Private::getNamespace);
-        //%% [optional] File file: file info (if this node represents a file)
-        s_inst.addProperty("file",&Private::getFile);
-        //%% [optional] Dir dir: directory info (if this node represents a directory)
-        s_inst.addProperty("dir",&Private::getDir);
-        //%% [optional] Page page: page info (if this node represents a page)
-        s_inst.addProperty("page",&Private::getPage);
-        //%% [optional] Module module: module info (if this node represents a module)
-        s_inst.addProperty("module",&Private::getModule);
-        //%% [optional] Member member: member info (if this node represents a member)
-        s_inst.addProperty("member",&Private::getMember);
-        //%% int id
-        s_inst.addProperty("id",&Private::id);
-        //%% string level
-        s_inst.addProperty("level",&Private::level);
-        //%% string name
-        s_inst.addProperty("name",&Private::name);
-        //%% string brief
-        s_inst.addProperty("brief",&Private::brief);
-        //%% bool isLinkable
-        s_inst.addProperty("isLinkable",&Private::isLinkable);
-        s_inst.addProperty("partOfGroup",&Private::partOfGroup);
-        s_inst.addProperty("anchor",&Private::anchor);
-        s_inst.addProperty("fileName",&Private::fileName);
-        s_inst.addProperty("isReference",&Private::isReference);
-        s_inst.addProperty("externalReference",&Private::externalReference);
-        init=TRUE;
-      }
-
+      m_children = std::dynamic_pointer_cast<NestingContext>(NestingContext::alloc(thisNode,m_type,level+1));
+      m_members = std::dynamic_pointer_cast<NestingContext>(NestingContext::alloc(thisNode,m_type,level+1));
       addNamespaces(addCls,addCps,visitedClasses);
       addClasses(inherit,hideSuper,visitedClasses);
       addDirFiles(visitedClasses);
@@ -6442,135 +5311,11 @@ class NestingNodeContext::Private
       addModules(visitedClasses);
       addMembers(visitedClasses);
     }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant isLeafNode() const
-    {
-      return m_children->count()==0;
-    }
-    TemplateVariant children() const
-    {
-      return m_children.get();
-    }
-    TemplateVariant members() const
-    {
-      return m_members.get();
-    }
-    TemplateVariant getClass() const
-    {
-      if (!m_cache.classContext && m_def->definitionType()==Definition::TypeClass)
-      {
-        m_cache.classContext.reset(ClassContext::alloc(toClassDef(m_def)));
-      }
-      if (m_cache.classContext)
-      {
-        return m_cache.classContext.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
-    }
-    TemplateVariant getNamespace() const
-    {
-      if (!m_cache.namespaceContext && m_def->definitionType()==Definition::TypeNamespace)
-      {
-        m_cache.namespaceContext.reset(NamespaceContext::alloc(toNamespaceDef(m_def)));
-      }
-      if (m_cache.namespaceContext)
-      {
-        return m_cache.namespaceContext.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
-    }
-    TemplateVariant getDir() const
-    {
-      if (!m_cache.dirContext && m_def->definitionType()==Definition::TypeDir)
-      {
-        m_cache.dirContext.reset(DirContext::alloc(toDirDef(m_def)));
-      }
-      if (m_cache.dirContext)
-      {
-        return m_cache.dirContext.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
-    }
-    TemplateVariant getFile() const
-    {
-      if (!m_cache.fileContext && m_def->definitionType()==Definition::TypeFile)
-      {
-        m_cache.fileContext.reset(FileContext::alloc(toFileDef(m_def)));
-      }
-      if (m_cache.fileContext)
-      {
-        return m_cache.fileContext.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
-    }
-    TemplateVariant getPage() const
-    {
-      if (!m_cache.pageContext && m_def->definitionType()==Definition::TypePage)
-      {
-        m_cache.pageContext.reset(PageContext::alloc(toPageDef(m_def),FALSE,FALSE));
-      }
-      if (m_cache.pageContext)
-      {
-        return m_cache.pageContext.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
-    }
-    TemplateVariant getModule() const
-    {
-      if (!m_cache.moduleContext && m_def->definitionType()==Definition::TypeGroup)
-      {
-        m_cache.moduleContext.reset(ModuleContext::alloc(toGroupDef(m_def)));
-      }
-      if (m_cache.moduleContext)
-      {
-        return m_cache.moduleContext.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
-    }
-    TemplateVariant getMember() const
-    {
-      if (!m_cache.memberContext && m_def->definitionType()==Definition::TypeMember)
-      {
-        m_cache.memberContext.reset(MemberContext::alloc(toMemberDef(m_def)));
-      }
-      if (m_cache.memberContext)
-      {
-        return m_cache.memberContext.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
-    }
-    TemplateVariant level() const
-    {
-      return m_level;
-    }
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
     TemplateVariant id() const
     {
       QCString result;
@@ -6578,6 +5323,26 @@ class NestingNodeContext::Private
       result+=QCString().setNum(m_index)+"_";
       return result;
     }
+
+  private:
+    // Property getters
+    TemplateVariant isLeafNode() const        { return m_children->count()==0; }
+    TemplateVariant children() const          { return std::static_pointer_cast<TemplateListIntf>(m_children); }
+    TemplateVariant members() const           { return std::static_pointer_cast<TemplateListIntf>(m_members); }
+    TemplateVariant getClass() const          { return m_class.get(this); }
+    TemplateVariant getNamespace() const      { return m_namespace.get(this); }
+    TemplateVariant getDir() const            { return m_dir.get(this); }
+    TemplateVariant getFile() const           { return m_file.get(this); }
+    TemplateVariant getPage() const           { return m_page.get(this); }
+    TemplateVariant getModule() const         { return m_module.get(this); }
+    TemplateVariant getMember() const         { return m_member.get(this); }
+    TemplateVariant level() const             { return m_level; }
+    TemplateVariant brief() const             { return m_brief.get(this); }
+    TemplateVariant isLinkable() const        { return m_def->isLinkable(); }
+    TemplateVariant anchor() const            { return m_def->anchor(); }
+    TemplateVariant fileName() const          { return m_def->getOutputFileBase(); }
+    TemplateVariant isReference() const       { return m_def->isReference(); }
+    TemplateVariant externalReference() const { return m_def->externalReference(relPathAsString()); }
     TemplateVariant name() const
     {
       if (m_def->definitionType()==Definition::TypeMember && m_type==ContextTreeType::Module)
@@ -6599,42 +5364,6 @@ class NestingNodeContext::Private
       static bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
       return createSubdirs ? QCString("../../") : QCString("");
     }
-    TemplateVariant brief() const
-    {
-      if (!m_cache.brief)
-      {
-        if (m_def->hasBriefDescription())
-        {
-          m_cache.brief.reset(new TemplateVariant(parseDoc(m_def,m_def->briefFile(),m_def->briefLine(),
-                              "",m_def->briefDescription(),TRUE)));
-        }
-        else
-        {
-          m_cache.brief.reset(new TemplateVariant(""));
-        }
-      }
-      return *m_cache.brief;
-    }
-    TemplateVariant isLinkable() const
-    {
-      return m_def->isLinkable();
-    }
-    TemplateVariant anchor() const
-    {
-      return m_def->anchor();
-    }
-    TemplateVariant fileName() const
-    {
-      return m_def->getOutputFileBase();
-    }
-    TemplateVariant isReference() const
-    {
-      return m_def->isReference();
-    }
-    TemplateVariant externalReference() const
-    {
-      return m_def->externalReference(relPathAsString());
-    }
 
     //------------------------------------------------------------------
 
@@ -6817,30 +5546,115 @@ class NestingNodeContext::Private
       }
     }
   private:
+    TemplateVariant createClass() const
+    {
+      return m_def->definitionType()==Definition::TypeClass ?
+          TemplateVariant(ClassContext::alloc(toClassDef(m_def))) :
+          TemplateVariant(false);
+    }
+    TemplateVariant createNamespace() const
+    {
+      return m_def->definitionType()==Definition::TypeNamespace ?
+          TemplateVariant(NamespaceContext::alloc(toNamespaceDef(m_def))) :
+          TemplateVariant(false);
+    }
+    TemplateVariant createDir() const
+    {
+      return m_def->definitionType()==Definition::TypeDir ?
+          TemplateVariant(DirContext::alloc(toDirDef(m_def))) :
+          TemplateVariant(false);
+    }
+    TemplateVariant createFile() const
+    {
+      return m_def->definitionType()==Definition::TypeFile ?
+          TemplateVariant(FileContext::alloc(toFileDef(m_def))) :
+          TemplateVariant(false);
+    }
+    TemplateVariant createPage() const
+    {
+      return m_def->definitionType()==Definition::TypePage ?
+          TemplateVariant(PageContext::alloc(toPageDef(m_def),FALSE,FALSE)) :
+          TemplateVariant(false);
+    }
+    TemplateVariant createModule() const
+    {
+      return m_def->definitionType()==Definition::TypeGroup ?
+          TemplateVariant(ModuleContext::alloc(toGroupDef(m_def))) :
+          TemplateVariant(false);
+    }
+    TemplateVariant createMember() const
+    {
+      return m_def->definitionType()==Definition::TypeMember ?
+          TemplateVariant(MemberContext::alloc(toMemberDef(m_def))) :
+          TemplateVariant(false);
+    }
+    TemplateVariant createBrief() const
+    {
+      return m_def->hasBriefDescription() ?
+          TemplateVariant(parseDoc(m_def,m_def->briefFile(),m_def->briefLine(),
+                          "",m_def->briefDescription(),TRUE)) :
+          TemplateVariant("");
+    }
+
     const NestingNodeContext *m_parent;
     ContextTreeType m_type;
     const Definition *m_def;
-    SharedPtr<NestingContext> m_children;
-    SharedPtr<NestingContext> m_members;
+    std::shared_ptr<NestingContext> m_children;
+    std::shared_ptr<NestingContext> m_members;
     int m_level;
     int m_index;
-    struct Cachable
-    {
-      SharedPtr<ClassContext>     classContext;
-      SharedPtr<NamespaceContext> namespaceContext;
-      SharedPtr<DirContext>       dirContext;
-      SharedPtr<FileContext>      fileContext;
-      SharedPtr<PageContext>      pageContext;
-      SharedPtr<ModuleContext>    moduleContext;
-      SharedPtr<MemberContext>    memberContext;
-      std::unique_ptr<TemplateVariant>  brief;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<NestingNodeContext::Private> s_inst;
+    CachedItem<TemplateVariant,  Private, &Private::createClass>     m_class;
+    CachedItem<TemplateVariant,  Private, &Private::createNamespace> m_namespace;
+    CachedItem<TemplateVariant,  Private, &Private::createDir>       m_dir;
+    CachedItem<TemplateVariant,  Private, &Private::createFile>      m_file;
+    CachedItem<TemplateVariant,  Private, &Private::createPage>      m_page;
+    CachedItem<TemplateVariant,  Private, &Private::createModule>    m_module;
+    CachedItem<TemplateVariant,  Private, &Private::createMember>    m_member;
+    CachedItem<TemplateVariant,  Private, &Private::createBrief>     m_brief;
+    static const PropertyMap<NestingNodeContext::Private> s_inst;
+};
+
+//%% struct NestingNode: node is a nesting relation tree
+//%% {
+const PropertyMap<NestingNodeContext::Private> NestingNodeContext::Private::s_inst {
+  //%% bool is_leaf_node: true if this node does not have any children
+  {  "is_leaf_node",&Private::isLeafNode },
+  //%% Nesting children: list of nested classes/namespaces
+  {  "children",&Private::children },
+  //%% Nesting children: list of nested classes/namespaces
+  {  "members",&Private::members },
+  //%% [optional] Class class: class info (if this node represents a class)
+  {  "class",&Private::getClass },
+  //%% [optional] Namespace namespace: namespace info (if this node represents a namespace)
+  {  "namespace",&Private::getNamespace },
+  //%% [optional] File file: file info (if this node represents a file)
+  {  "file",&Private::getFile },
+  //%% [optional] Dir dir: directory info (if this node represents a directory)
+  {  "dir",&Private::getDir },
+  //%% [optional] Page page: page info (if this node represents a page)
+  {  "page",&Private::getPage },
+  //%% [optional] Module module: module info (if this node represents a module)
+  {  "module",&Private::getModule },
+  //%% [optional] Member member: member info (if this node represents a member)
+  {  "member",&Private::getMember },
+  //%% int id
+  {  "id",&Private::id },
+  //%% string level
+  {  "level",&Private::level },
+  //%% string name
+  {  "name",&Private::name },
+  //%% string brief
+  {  "brief",&Private::brief },
+  //%% bool isLinkable
+  {  "isLinkable",&Private::isLinkable },
+  {  "partOfGroup",&Private::partOfGroup },
+  {  "anchor",&Private::anchor },
+  {  "fileName",&Private::fileName },
+  {  "isReference",&Private::isReference },
+  {  "externalReference",&Private::externalReference }
 };
 //%% }
 
-PropertyMapper<NestingNodeContext::Private> NestingNodeContext::Private::s_inst;
 
 NestingNodeContext::NestingNodeContext(const NestingNodeContext *parent,
                                        ContextTreeType type,
@@ -6848,14 +5662,12 @@ NestingNodeContext::NestingNodeContext(const NestingNodeContext *parent,
                                        bool addClass,bool addConcepts,
                                        bool inherit,bool hideSuper,
                                        ClassDefSet &visitedClasses)
-   : RefCountedContext("NestingNodeContext")
+  : p(std::make_unique<Private>(parent,this,type,d,index,level,addClass,addConcepts,inherit,hideSuper,visitedClasses))
 {
-  p = new Private(parent,this,type,d,index,level,addClass,addConcepts,inherit,hideSuper,visitedClasses);
 }
 
 NestingNodeContext::~NestingNodeContext()
 {
-  delete p;
 }
 
 TemplateVariant NestingNodeContext::get(const QCString &n) const
@@ -6895,9 +5707,8 @@ class NestingContext::Private : public GenericNodeListContext
         bool isLinkable  = nd->isLinkableInProject();
         if (isLinkable && hasChildren)
         {
-          NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,m_type,nd,m_index,m_level,
-                                    addClasses,addConcepts,FALSE,FALSE,visitedClasses);
-          append(nnc);
+          append(NestingNodeContext::alloc(m_parent,m_type,nd,m_index,m_level,
+                                           addClasses,addConcepts,FALSE,FALSE,visitedClasses));
           m_index++;
         }
       }
@@ -6934,9 +5745,8 @@ class NestingContext::Private : public GenericNodeListContext
       {
         if (classVisibleInIndex(cd) && cd->templateMaster()==0)
         {
-          NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level,
-                                                              TRUE,FALSE,FALSE,FALSE,visitedClasses);
-          append(nnc);
+          append(NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level,
+                                           TRUE,FALSE,FALSE,FALSE,visitedClasses));
           m_index++;
         }
       }
@@ -6947,9 +5757,8 @@ class NestingContext::Private : public GenericNodeListContext
       {
         if (cd->isLinkable())
         {
-          NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level,
-                                                              FALSE,TRUE,FALSE,FALSE,visitedClasses);
-          append(nnc);
+          append(NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level,
+                                           FALSE,TRUE,FALSE,FALSE,visitedClasses));
           m_index++;
         }
       }
@@ -7011,9 +5820,8 @@ class NestingContext::Private : public GenericNodeListContext
         {
           if (fd->getDirDef()==0) // top level file
           {
-            NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,m_type,fd.get(),m_index,m_level,
-                                          FALSE,FALSE,FALSE,FALSE,visitedClasses);
-            append(nnc);
+            append(NestingNodeContext::alloc(m_parent,m_type,fd.get(),m_index,m_level,
+                                             FALSE,FALSE,FALSE,FALSE,visitedClasses));
             m_index++;
           }
         }
@@ -7023,9 +5831,8 @@ class NestingContext::Private : public GenericNodeListContext
     {
       for (const auto &fd : fList)
       {
-        NestingNodeContext *nnc=NestingNodeContext::alloc(m_parent,m_type,fd,m_index,m_level,
-                                          FALSE,FALSE,FALSE,FALSE,visitedClasses);
-        append(nnc);
+        append(NestingNodeContext::alloc(m_parent,m_type,fd,m_index,m_level,
+                                         FALSE,FALSE,FALSE,FALSE,visitedClasses));
         m_index++;
       }
     }
@@ -7103,9 +5910,8 @@ class NestingContext::Private : public GenericNodeListContext
 
         if (cd->isVisibleInHierarchy() && b)
         {
-          NestingNodeContext *tnc = NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level,
-                                           TRUE,FALSE,TRUE,hideSuper,visitedClasses);
-          append(tnc);
+          append(NestingNodeContext::alloc(m_parent,m_type,cd,m_index,m_level,
+                                           TRUE,FALSE,TRUE,hideSuper,visitedClasses));
           m_index++;
         }
       }
@@ -7132,9 +5938,8 @@ class NestingContext::Private : public GenericNodeListContext
           if (cd->isVisibleInHierarchy()) // should it be visible
           {
             // new root level class
-            NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,m_type,cd.get(),m_index,m_level,
-                                             TRUE,FALSE,TRUE,FALSE,visitedClasses);
-            append(nnc);
+            append(NestingNodeContext::alloc(m_parent,m_type,cd.get(),m_index,m_level,
+                                             TRUE,FALSE,TRUE,FALSE,visitedClasses));
             m_index++;
           }
         }
@@ -7146,9 +5951,8 @@ class NestingContext::Private : public GenericNodeListContext
       {
         if (md->visibleInIndex())
         {
-          NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,m_type,md,m_index,m_level+1,
-              TRUE,FALSE,TRUE,FALSE,visitedClasses);
-          append(nnc);
+          append(NestingNodeContext::alloc(m_parent,m_type,md,m_index,m_level+1,
+                                           TRUE,FALSE,TRUE,FALSE,visitedClasses));
           m_index++;
         }
       }
@@ -7161,15 +5965,12 @@ class NestingContext::Private : public GenericNodeListContext
     int m_index = 0;
 };
 
-NestingContext::NestingContext(const NestingNodeContext *parent,ContextTreeType type,int level) :
-     RefCountedContext("NestingContext")
+NestingContext::NestingContext(const NestingNodeContext *parent,ContextTreeType type,int level) : p(std::make_unique<Private>(parent,type,level))
 {
-  p = new Private(parent,type,level);
 }
 
 NestingContext::~NestingContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -7183,7 +5984,7 @@ TemplateVariant NestingContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *NestingContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr NestingContext::createIterator() const
 {
   return p->createIterator();
 }
@@ -7276,121 +6077,73 @@ void NestingContext::addMembers(const MemberVector &mv,ClassDefSet &visitedClass
 
 //------------------------------------------------------------------------
 
-//%% struct ClassTree: Class nesting relations
-//%% {
 class ClassTreeContext::Private
 {
   public:
     Private()
     {
-      m_classTree.reset(NestingContext::alloc(0,ContextTreeType::ClassNesting,0));
+      m_classTree = NestingContext::alloc(0,ContextTreeType::ClassNesting,0);
+      auto ctx = std::dynamic_pointer_cast<NestingContext>(m_classTree);
       ClassDefSet visitedClasses;
-      m_classTree->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,TRUE,FALSE,visitedClasses);
-      m_classTree->addClasses(*Doxygen::classLinkedMap,TRUE,visitedClasses);
-      //%% Nesting tree
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("tree",          &Private::tree);
-        s_inst.addProperty("fileName",      &Private::fileName);
-        s_inst.addProperty("relPath",       &Private::relPath);
-        s_inst.addProperty("highlight",     &Private::highlight);
-        s_inst.addProperty("subhighlight",  &Private::subhighlight);
-        s_inst.addProperty("title",         &Private::title);
-        s_inst.addProperty("preferredDepth",&Private::preferredDepth);
-        s_inst.addProperty("maxDepth",      &Private::maxDepth);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant tree() const
-    {
-      return m_classTree.get();
-    }
-    TemplateVariant fileName() const
-    {
-      return "annotated";
-    }
-    TemplateVariant relPath() const
-    {
-      return "";
-    }
-    TemplateVariant highlight() const
-    {
-      return "classes";
-    }
-    TemplateVariant subhighlight() const
-    {
-      return "classlist";
+      ctx->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,TRUE,FALSE,visitedClasses);
+      ctx->addClasses(*Doxygen::classLinkedMap,TRUE,visitedClasses);
     }
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant tree() const                 { return TemplateVariant(m_classTree); }
+    TemplateVariant fileName() const             { return "annotated"; }
+    TemplateVariant relPath() const              { return ""; }
+    TemplateVariant highlight() const            { return "classes"; }
+    TemplateVariant subhighlight() const         { return "classlist"; }
+    TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
+    TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
     TemplateVariant title() const
     {
-      static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
-      static bool vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
-      if (fortranOpt)
-      {
-        return theTranslator->trCompoundListFortran();
-      }
-      else if (vhdlOpt)
-      {
-        return theTranslator->trDesignUnitList();
-      }
-      else
-      {
-        return theTranslator->trClasses();
-      }
+      return Config_getBool(OPTIMIZE_FOR_FORTRAN) ? theTranslator->trCompoundListFortran() :
+             Config_getBool(OPTIMIZE_OUTPUT_VHDL) ? theTranslator->trDesignUnitList()      :
+                                                    theTranslator->trClasses();
     }
-    TemplateVariant maxDepth() const
+  private:
+    int createMaxDepth() const
     {
-      if (!m_cache.maxDepthComputed)
-      {
-        m_cache.maxDepth = computeMaxDepth(m_classTree.get());
-        m_cache.maxDepthComputed=TRUE;
-      }
-      return m_cache.maxDepth;
+      return computeMaxDepth(m_classTree);
     }
-    TemplateVariant preferredDepth() const
+    int createPreferredDepth() const
     {
-      if (!m_cache.preferredDepthComputed)
-      {
-        m_cache.preferredDepth = computePreferredDepth(m_classTree.get(),maxDepth().toInt());
-        m_cache.preferredDepthComputed=TRUE;
-      }
-      return m_cache.preferredDepth;
+      return computePreferredDepth(m_classTree,m_maxDepth.get(this));
     }
-  private:
-    SharedPtr<NestingContext> m_classTree;
-    struct Cachable
-    {
-      Cachable() : maxDepth(0), maxDepthComputed(FALSE),
-                   preferredDepth(0), preferredDepthComputed(FALSE) {}
-      int   maxDepth;
-      bool  maxDepthComputed;
-      int   preferredDepth;
-      bool  preferredDepthComputed;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<ClassTreeContext::Private> s_inst;
+    TemplateListIntfPtr m_classTree;
+    CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
+    CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
+    static const PropertyMap<ClassTreeContext::Private> s_inst;
+};
+
+//%% struct ClassTree: Class nesting relations
+//%% {
+const PropertyMap<ClassTreeContext::Private> ClassTreeContext::Private::s_inst {
+  {  "tree",          &Private::tree },
+  {  "fileName",      &Private::fileName },
+  {  "relPath",       &Private::relPath },
+  {  "highlight",     &Private::highlight },
+  {  "subhighlight",  &Private::subhighlight },
+  {  "title",         &Private::title },
+  {  "preferredDepth",&Private::preferredDepth },
+  {  "maxDepth",      &Private::maxDepth }
 };
 //%% }
 
-PropertyMapper<ClassTreeContext::Private> ClassTreeContext::Private::s_inst;
 
-ClassTreeContext::ClassTreeContext() : RefCountedContext("ClassTreeContext")
+ClassTreeContext::ClassTreeContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 ClassTreeContext::~ClassTreeContext()
 {
-  delete p;
 }
 
 TemplateVariant ClassTreeContext::get(const QCString &name) const
@@ -7421,15 +6174,13 @@ class ConceptListContext::Private : public GenericNodeListContext
     }
 };
 
-ConceptListContext::ConceptListContext() : RefCountedContext("ConceptListContext")
+ConceptListContext::ConceptListContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
   p->addConcepts(*Doxygen::conceptLinkedMap);
 }
 
 ConceptListContext::~ConceptListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -7443,7 +6194,7 @@ TemplateVariant ConceptListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *ConceptListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr ConceptListContext::createIterator() const
 {
   return p->createIterator();
 }
@@ -7466,15 +6217,13 @@ class NamespaceListContext::Private : public GenericNodeListContext
     }
 };
 
-NamespaceListContext::NamespaceListContext() : RefCountedContext("NamespaceListContext")
+NamespaceListContext::NamespaceListContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
   p->addNamespaces(*Doxygen::namespaceLinkedMap);
 }
 
 NamespaceListContext::~NamespaceListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -7488,129 +6237,81 @@ TemplateVariant NamespaceListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *NamespaceListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr NamespaceListContext::createIterator() const
 {
   return p->createIterator();
 }
 
 //------------------------------------------------------------------------
 
-//%% struct NamespaceTree: tree of nested namespace
-//%% {
 class NamespaceTreeContext::Private
 {
   public:
     Private()
     {
-      m_namespaceTree.reset(NestingContext::alloc(0,ContextTreeType::Namespace,0));
+      m_namespaceTree = NestingContext::alloc(0,ContextTreeType::Namespace,0);
+      auto ctx = std::dynamic_pointer_cast<NestingContext>(m_namespaceTree);
       ClassDefSet visitedClasses;
-      m_namespaceTree->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,FALSE,TRUE,visitedClasses);
-      //%% Nesting tree
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("tree",          &Private::tree);
-        s_inst.addProperty("fileName",      &Private::fileName);
-        s_inst.addProperty("relPath",       &Private::relPath);
-        s_inst.addProperty("highlight",     &Private::highlight);
-        s_inst.addProperty("subhighlight",  &Private::subhighlight);
-        s_inst.addProperty("title",         &Private::title);
-        s_inst.addProperty("preferredDepth",&Private::preferredDepth);
-        s_inst.addProperty("maxDepth",      &Private::maxDepth);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant tree() const
-    {
-      return m_namespaceTree.get();
-    }
-    TemplateVariant fileName() const
-    {
-      return "namespaces";
-    }
-    TemplateVariant relPath() const
-    {
-      return "";
-    }
-    TemplateVariant highlight() const
-    {
-      return "namespaces";
-    }
-    TemplateVariant subhighlight() const
-    {
-      return "namespacelist";
+      ctx->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,FALSE,TRUE,visitedClasses);
     }
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant tree() const                 { return TemplateVariant(m_namespaceTree); }
+    TemplateVariant fileName() const             { return "namespaces"; }
+    TemplateVariant relPath() const              { return ""; }
+    TemplateVariant highlight() const            { return "namespaces"; }
+    TemplateVariant subhighlight() const         { return "namespacelist"; }
+    TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
+    TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
     TemplateVariant title() const
     {
-      static bool javaOpt    = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
-      static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
-      static bool vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
-      static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
-      if (javaOpt || vhdlOpt)
-      {
-        return theTranslator->trPackages();
-      }
-      else if (fortranOpt || sliceOpt)
-      {
-        return theTranslator->trModulesList();
-      }
-      else
-      {
-        return theTranslator->trNamespaceList();
-      }
+      return Config_getBool(OPTIMIZE_OUTPUT_JAVA)  ? theTranslator->trPackages()     :
+             Config_getBool(OPTIMIZE_OUTPUT_VHDL)  ? theTranslator->trPackages()     :
+             Config_getBool(OPTIMIZE_FOR_FORTRAN)  ? theTranslator->trModulesList()  :
+             Config_getBool(OPTIMIZE_OUTPUT_SLICE) ? theTranslator->trModulesList()  :
+                                                     theTranslator->trNamespaceList();
     }
-    TemplateVariant maxDepth() const
+
+  private:
+    int createMaxDepth() const
     {
-      if (!m_cache.maxDepthComputed)
-      {
-        m_cache.maxDepth = computeMaxDepth(m_namespaceTree.get());
-        m_cache.maxDepthComputed=TRUE;
-      }
-      return m_cache.maxDepth;
+      return computeMaxDepth(m_namespaceTree);
     }
-    TemplateVariant preferredDepth() const
+    int createPreferredDepth() const
     {
-      if (!m_cache.preferredDepthComputed)
-      {
-        m_cache.preferredDepth = computePreferredDepth(m_namespaceTree.get(),maxDepth().toInt());
-        m_cache.preferredDepthComputed=TRUE;
-      }
-      return m_cache.preferredDepth;
+      return computePreferredDepth(m_namespaceTree,m_maxDepth.get(this));
     }
-  private:
-    SharedPtr<NestingContext> m_namespaceTree;
-    struct Cachable
-    {
-      Cachable() : maxDepth(0), maxDepthComputed(FALSE),
-                   preferredDepth(0), preferredDepthComputed(FALSE) {}
-      int   maxDepth;
-      bool  maxDepthComputed;
-      int   preferredDepth;
-      bool  preferredDepthComputed;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<NamespaceTreeContext::Private> s_inst;
+    TemplateListIntfPtr m_namespaceTree;
+    CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
+    CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
+    static const PropertyMap<NamespaceTreeContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<NamespaceTreeContext::Private> NamespaceTreeContext::Private::s_inst;
+//%% struct NamespaceTree: tree of nested namespace
+//%% {
+const PropertyMap<NamespaceTreeContext::Private> NamespaceTreeContext::Private::s_inst {
+  {  "tree",          &Private::tree },
+  {  "fileName",      &Private::fileName },
+  {  "relPath",       &Private::relPath },
+  {  "highlight",     &Private::highlight },
+  {  "subhighlight",  &Private::subhighlight },
+  {  "title",         &Private::title },
+  {  "preferredDepth",&Private::preferredDepth },
+  {  "maxDepth",      &Private::maxDepth }
+};
+//%% }
 
-NamespaceTreeContext::NamespaceTreeContext() : RefCountedContext("NamespaceTreeContext")
+NamespaceTreeContext::NamespaceTreeContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 NamespaceTreeContext::~NamespaceTreeContext()
 {
-  delete p;
 }
 
 TemplateVariant NamespaceTreeContext::get(const QCString &name) const
@@ -7649,15 +6350,13 @@ class FileListContext::Private : public GenericNodeListContext
     }
 };
 
-FileListContext::FileListContext() : RefCountedContext("FileListContext")
+FileListContext::FileListContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
   if (Doxygen::inputNameLinkedMap) p->addFiles(*Doxygen::inputNameLinkedMap);
 }
 
 FileListContext::~FileListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -7671,7 +6370,7 @@ TemplateVariant FileListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *FileListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr FileListContext::createIterator() const
 {
   return p->createIterator();
 }
@@ -7691,14 +6390,12 @@ class DirListContext::Private : public GenericNodeListContext
     }
 };
 
-DirListContext::DirListContext() : RefCountedContext("DirListContext")
+DirListContext::DirListContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 DirListContext::~DirListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -7712,7 +6409,7 @@ TemplateVariant DirListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *DirListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr DirListContext::createIterator() const
 {
   return p->createIterator();
 }
@@ -7730,9 +6427,8 @@ class UsedFilesContext::Private : public GenericNodeListContext
     }
 };
 
-UsedFilesContext::UsedFilesContext(const ClassDef *cd) : RefCountedContext("UsedFilesContext")
+UsedFilesContext::UsedFilesContext(const ClassDef *cd) : p(std::make_unique<Private>())
 {
-  p = new Private;
   if (cd)
   {
     for (const auto &fd : cd->usedFiles())
@@ -7744,7 +6440,6 @@ UsedFilesContext::UsedFilesContext(const ClassDef *cd) : RefCountedContext("Used
 
 UsedFilesContext::~UsedFilesContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -7758,7 +6453,7 @@ TemplateVariant UsedFilesContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *UsedFilesContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr UsedFilesContext::createIterator() const
 {
   return p->createIterator();
 }
@@ -7770,112 +6465,74 @@ void UsedFilesContext::addFile(const FileDef *fd)
 
 //------------------------------------------------------------------------
 
-//%% struct FileTree: tree of directories and files
-//%% {
 class FileTreeContext::Private
 {
   public:
     Private()
     {
       // Add dirs tree
-      m_dirFileTree.reset(NestingContext::alloc(0,ContextTreeType::File,0));
+      m_dirFileTree = NestingContext::alloc(0,ContextTreeType::File,0);
+      auto ctx = std::dynamic_pointer_cast<NestingContext>(m_dirFileTree);
       ClassDefSet visitedClasses;
-      m_dirFileTree->addDirs(*Doxygen::dirLinkedMap,visitedClasses);
+      ctx->addDirs(*Doxygen::dirLinkedMap,visitedClasses);
       if (Doxygen::inputNameLinkedMap)
       {
-        m_dirFileTree->addFiles(*Doxygen::inputNameLinkedMap,visitedClasses);
-      }
-      //%% DirFile tree:
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("tree",          &Private::tree);
-        s_inst.addProperty("fileName",      &Private::fileName);
-        s_inst.addProperty("relPath",       &Private::relPath);
-        s_inst.addProperty("highlight",     &Private::highlight);
-        s_inst.addProperty("subhighlight",  &Private::subhighlight);
-        s_inst.addProperty("title",         &Private::title);
-        s_inst.addProperty("preferredDepth",&Private::preferredDepth);
-        s_inst.addProperty("maxDepth",      &Private::maxDepth);
-        init=TRUE;
+        ctx->addFiles(*Doxygen::inputNameLinkedMap,visitedClasses);
       }
     }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant tree() const
-    {
-      return m_dirFileTree.get();
-    }
-    TemplateVariant fileName() const
-    {
-      return "files";
-    }
-    TemplateVariant relPath() const
-    {
-      return "";
-    }
-    TemplateVariant highlight() const
-    {
-      return "files";
-    }
-    TemplateVariant subhighlight() const
-    {
-      return "filelist";
-    }
-    TemplateVariant title() const
-    {
-      return theTranslator->trFileList();
-    }
-    TemplateVariant maxDepth() const
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant tree() const                 { return TemplateVariant(m_dirFileTree); }
+    TemplateVariant fileName() const             { return "files"; }
+    TemplateVariant relPath() const              { return ""; }
+    TemplateVariant highlight() const            { return "files"; }
+    TemplateVariant subhighlight() const         { return "filelist"; }
+    TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
+    TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
+    TemplateVariant title() const                { return theTranslator->trFileList(); }
+
+  private:
+    int createMaxDepth() const
     {
-      if (!m_cache.maxDepthComputed)
-      {
-        m_cache.maxDepth = computeMaxDepth(m_dirFileTree.get());
-        m_cache.maxDepthComputed=TRUE;
-      }
-      return m_cache.maxDepth;
+      return computeMaxDepth(m_dirFileTree);
     }
-    TemplateVariant preferredDepth() const
+    int createPreferredDepth() const
     {
-      if (!m_cache.preferredDepthComputed)
-      {
-        m_cache.preferredDepth = computePreferredDepth(m_dirFileTree.get(),maxDepth().toInt());
-        m_cache.preferredDepthComputed=TRUE;
-      }
-      return m_cache.preferredDepth;
+      return computePreferredDepth(m_dirFileTree,m_maxDepth.get(this));
     }
-  private:
-    SharedPtr<NestingContext> m_dirFileTree;
-    struct Cachable
-    {
-      Cachable() : maxDepth(0), maxDepthComputed(FALSE),
-                   preferredDepth(0), preferredDepthComputed(FALSE) {}
-      int   maxDepth;
-      bool  maxDepthComputed;
-      int   preferredDepth;
-      bool  preferredDepthComputed;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<FileTreeContext::Private> s_inst;
+    TemplateListIntfPtr m_dirFileTree;
+    CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
+    CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
+    static const PropertyMap<FileTreeContext::Private> s_inst;
+};
+
+//%% struct FileTree: tree of directories and files
+//%% {
+const PropertyMap<FileTreeContext::Private> FileTreeContext::Private::s_inst {
+  {  "tree",          &Private::tree },
+  {  "fileName",      &Private::fileName },
+  {  "relPath",       &Private::relPath },
+  {  "highlight",     &Private::highlight },
+  {  "subhighlight",  &Private::subhighlight },
+  {  "title",         &Private::title },
+  {  "preferredDepth",&Private::preferredDepth },
+  {  "maxDepth",      &Private::maxDepth }
 };
 //%% }
 
-PropertyMapper<FileTreeContext::Private> FileTreeContext::Private::s_inst;
+//PropertyMapper<FileTreeContext::Private> FileTreeContext::Private::s_inst;
 
-FileTreeContext::FileTreeContext() : RefCountedContext("FileTreeContext")
+FileTreeContext::FileTreeContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 FileTreeContext::~FileTreeContext()
 {
-  delete p;
 }
 
 TemplateVariant FileTreeContext::get(const QCString &name) const
@@ -7890,109 +6547,69 @@ StringVector FileTreeContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct PageTree: tree of related pages
-//%% {
 class PageTreeContext::Private
 {
   public:
     Private(const PageLinkedMap &pages)
     {
-      m_pageTree.reset(NestingContext::alloc(0,ContextTreeType::Page,0));
+      m_pageTree = NestingContext::alloc(0,ContextTreeType::Page,0);
+      auto ctx = std::dynamic_pointer_cast<NestingContext>(m_pageTree);
       ClassDefSet visitedClasses;
       // Add pages
-      m_pageTree->addPages(pages,TRUE,visitedClasses);
-
-      //%% PageNodeList tree:
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("tree",          &Private::tree);
-        s_inst.addProperty("fileName",      &Private::fileName);
-        s_inst.addProperty("relPath",       &Private::relPath);
-        s_inst.addProperty("highlight",     &Private::highlight);
-        s_inst.addProperty("subhighlight",  &Private::subhighlight);
-        s_inst.addProperty("title",         &Private::title);
-        s_inst.addProperty("preferredDepth",&Private::preferredDepth);
-        s_inst.addProperty("maxDepth",      &Private::maxDepth);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant tree() const
-    {
-      return m_pageTree.get();
-    }
-    TemplateVariant fileName() const
-    {
-      return "pages";
+      ctx->addPages(pages,TRUE,visitedClasses);
     }
-    TemplateVariant relPath() const
-    {
-      return "";
-    }
-    TemplateVariant highlight() const
-    {
-      return "pages";
-    }
-    TemplateVariant subhighlight() const
-    {
-      return "";
-    }
-    TemplateVariant title() const
-    {
-      return theTranslator->trRelatedPages();
-    }
-    TemplateVariant maxDepth() const
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant tree() const                 { return TemplateVariant(m_pageTree); }
+    TemplateVariant fileName() const             { return "pages"; }
+    TemplateVariant relPath() const              { return ""; }
+    TemplateVariant highlight() const            { return "pages"; }
+    TemplateVariant subhighlight() const         { return ""; }
+    TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
+    TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
+    TemplateVariant title() const                { return theTranslator->trRelatedPages(); }
+
+  private:
+    int createMaxDepth() const
     {
-      if (!m_cache.maxDepthComputed)
-      {
-        m_cache.maxDepth = computeMaxDepth(m_pageTree.get());
-        m_cache.maxDepthComputed=TRUE;
-      }
-      return m_cache.maxDepth;
+      return computeMaxDepth(m_pageTree);
     }
-    TemplateVariant preferredDepth() const
+    int createPreferredDepth() const
     {
-      if (!m_cache.preferredDepthComputed)
-      {
-        m_cache.preferredDepth = computePreferredDepth(m_pageTree.get(),maxDepth().toInt());
-        m_cache.preferredDepthComputed=TRUE;
-      }
-      return m_cache.preferredDepth;
+      return computePreferredDepth(m_pageTree,m_maxDepth.get(this));
     }
-  private:
-    SharedPtr<NestingContext> m_pageTree;
-    struct Cachable
-    {
-      Cachable() : maxDepth(0), maxDepthComputed(FALSE),
-                   preferredDepth(0), preferredDepthComputed(FALSE) {}
-      int   maxDepth;
-      bool  maxDepthComputed;
-      int   preferredDepth;
-      bool  preferredDepthComputed;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<PageTreeContext::Private> s_inst;
+    TemplateListIntfPtr m_pageTree;
+    CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
+    CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
+    static const PropertyMap<PageTreeContext::Private> s_inst;
+};
+
+//%% struct PageTree: tree of related pages
+//%% {
+const PropertyMap<PageTreeContext::Private> PageTreeContext::Private::s_inst {
+  {  "tree",          &Private::tree },
+  {  "fileName",      &Private::fileName },
+  {  "relPath",       &Private::relPath },
+  {  "highlight",     &Private::highlight },
+  {  "subhighlight",  &Private::subhighlight },
+  {  "title",         &Private::title },
+  {  "preferredDepth",&Private::preferredDepth },
+  {  "maxDepth",      &Private::maxDepth }
 };
 //%% }
 
-PropertyMapper<PageTreeContext::Private> PageTreeContext::Private::s_inst;
 
-PageTreeContext::PageTreeContext(const PageLinkedMap &pages) : RefCountedContext("PageTreeContext")
+PageTreeContext::PageTreeContext(const PageLinkedMap &pages) : p(std::make_unique<Private>(pages))
 {
-  p = new Private(pages);
 }
 
 PageTreeContext::~PageTreeContext()
 {
-  delete p;
 }
 
 TemplateVariant PageTreeContext::get(const QCString &name) const
@@ -8023,15 +6640,13 @@ class PageListContext::Private : public GenericNodeListContext
     }
 };
 
-PageListContext::PageListContext(const PageLinkedMap &pages) : RefCountedContext("PageListContext")
+PageListContext::PageListContext(const PageLinkedMap &pages) : p(std::make_unique<Private>())
 {
-  p = new Private;
   p->addPages(pages);
 }
 
 PageListContext::~PageListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -8045,7 +6660,7 @@ TemplateVariant PageListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *PageListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr PageListContext::createIterator() const
 {
   return p->createIterator();
 }
@@ -8068,14 +6683,12 @@ class ExampleListContext::Private : public GenericNodeListContext
     }
 };
 
-ExampleListContext::ExampleListContext() : RefCountedContext("ExampleListContext")
+ExampleListContext::ExampleListContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 ExampleListContext::~ExampleListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -8089,7 +6702,7 @@ TemplateVariant ExampleListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *ExampleListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr ExampleListContext::createIterator() const
 {
   return p->createIterator();
 }
@@ -8112,15 +6725,13 @@ class ModuleListContext::Private : public GenericNodeListContext
     }
 };
 
-ModuleListContext::ModuleListContext() : RefCountedContext("ModuleListContext")
+ModuleListContext::ModuleListContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
   p->addModules();
 }
 
 ModuleListContext::~ModuleListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -8134,117 +6745,77 @@ TemplateVariant ModuleListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *ModuleListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr ModuleListContext::createIterator() const
 {
   return p->createIterator();
 }
 
 //------------------------------------------------------------------------
 
-//%% struct ConceptTree: tree of modules
-//%% {
 class ConceptTreeContext::Private
 {
   public:
     Private()
     {
-      m_conceptTree.reset(NestingContext::alloc(0,ContextTreeType::Concept,0));
+      m_conceptTree = NestingContext::alloc(0,ContextTreeType::Concept,0);
+      auto ctx = std::dynamic_pointer_cast<NestingContext>(m_conceptTree);
       ClassDefSet visitedClasses;
       // Add concepts
-      m_conceptTree->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,FALSE,TRUE,visitedClasses);
-      m_conceptTree->addConcepts(*Doxygen::conceptLinkedMap,TRUE,visitedClasses);
-
-      //%% ConceptList tree:
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("tree",          &Private::tree);
-        s_inst.addProperty("fileName",      &Private::fileName);
-        s_inst.addProperty("relPath",       &Private::relPath);
-        s_inst.addProperty("highlight",     &Private::highlight);
-        s_inst.addProperty("subhighlight",  &Private::subhighlight);
-        s_inst.addProperty("title",         &Private::title);
-        s_inst.addProperty("preferredDepth",&Private::preferredDepth);
-        s_inst.addProperty("maxDepth",      &Private::maxDepth);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant tree() const
-    {
-      return m_conceptTree.get();
-    }
-    TemplateVariant fileName() const
-    {
-      return "concepts";
-    }
-    TemplateVariant relPath() const
-    {
-      return "";
-    }
-    TemplateVariant highlight() const
-    {
-      return "concepts";
-    }
-    TemplateVariant subhighlight() const
-    {
-      return "";
+      ctx->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,FALSE,TRUE,visitedClasses);
+      ctx->addConcepts(*Doxygen::conceptLinkedMap,TRUE,visitedClasses);
     }
-    TemplateVariant title() const
-    {
-      return theTranslator->trConcept(true,false);
-    }
-    TemplateVariant maxDepth() const
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant tree() const                 { return TemplateVariant(m_conceptTree); }
+    TemplateVariant fileName() const             { return "concepts"; }
+    TemplateVariant relPath() const              { return ""; }
+    TemplateVariant highlight() const            { return "concepts"; }
+    TemplateVariant subhighlight() const         { return ""; }
+    TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
+    TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
+    TemplateVariant title() const                { return theTranslator->trConcept(true,false); }
+
+  private:
+    int createMaxDepth() const
     {
-      if (!m_cache.maxDepthComputed)
-      {
-        m_cache.maxDepth = computeMaxDepth(m_conceptTree.get());
-        m_cache.maxDepthComputed=TRUE;
-      }
-      return m_cache.maxDepth;
+      return computeMaxDepth(m_conceptTree);
     }
-    TemplateVariant preferredDepth() const
+    int createPreferredDepth() const
     {
-      if (!m_cache.preferredDepthComputed)
-      {
-        m_cache.preferredDepth = computePreferredDepth(m_conceptTree.get(),maxDepth().toInt());
-        m_cache.preferredDepthComputed=TRUE;
-      }
-      return m_cache.preferredDepth;
+      return computePreferredDepth(m_conceptTree,m_maxDepth.get(this));
     }
-  private:
-    SharedPtr<NestingContext> m_conceptTree;
-    struct Cachable
-    {
-      Cachable() : maxDepth(0), maxDepthComputed(FALSE),
-                   preferredDepth(0), preferredDepthComputed(FALSE) {}
-      int   maxDepth;
-      bool  maxDepthComputed;
-      int   preferredDepth;
-      bool  preferredDepthComputed;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<ConceptTreeContext::Private> s_inst;
+    TemplateListIntfPtr m_conceptTree;
+    CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
+    CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
+    static const PropertyMap<ConceptTreeContext::Private> s_inst;
+};
+
+//%% struct ConceptTree: tree of modules
+//%% {
+const PropertyMap<ConceptTreeContext::Private> ConceptTreeContext::Private::s_inst {
+  {  "tree",          &Private::tree },
+  {  "fileName",      &Private::fileName },
+  {  "relPath",       &Private::relPath },
+  {  "highlight",     &Private::highlight },
+  {  "subhighlight",  &Private::subhighlight },
+  {  "title",         &Private::title },
+  {  "preferredDepth",&Private::preferredDepth },
+  {  "maxDepth",      &Private::maxDepth }
 };
 //%% }
 
-PropertyMapper<ConceptTreeContext::Private> ConceptTreeContext::Private::s_inst;
 
-ConceptTreeContext::ConceptTreeContext() : RefCountedContext("ConceptTreeContext")
+ConceptTreeContext::ConceptTreeContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 ConceptTreeContext::~ConceptTreeContext()
 {
-  delete p;
 }
 
 TemplateVariant ConceptTreeContext::get(const QCString &name) const
@@ -8259,162 +6830,177 @@ StringVector ConceptTreeContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct ModuleTree: tree of modules
-//%% {
 class ModuleTreeContext::Private
 {
   public:
     Private()
     {
-      m_moduleTree.reset(NestingContext::alloc(0,ContextTreeType::Module,0));
+      m_moduleTree = NestingContext::alloc(0,ContextTreeType::Module,0);
+      auto ctx = std::dynamic_pointer_cast<NestingContext>(m_moduleTree);
       ClassDefSet visitedClasses;
       // Add modules
-      m_moduleTree->addModules(*Doxygen::groupLinkedMap,visitedClasses);
-
-      //%% ModuleList tree:
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("tree",          &Private::tree);
-        s_inst.addProperty("fileName",      &Private::fileName);
-        s_inst.addProperty("relPath",       &Private::relPath);
-        s_inst.addProperty("highlight",     &Private::highlight);
-        s_inst.addProperty("subhighlight",  &Private::subhighlight);
-        s_inst.addProperty("title",         &Private::title);
-        s_inst.addProperty("preferredDepth",&Private::preferredDepth);
-        s_inst.addProperty("maxDepth",      &Private::maxDepth);
-        init=TRUE;
-      }
+      ctx->addModules(*Doxygen::groupLinkedMap,visitedClasses);
     }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant tree() const
-    {
-      return m_moduleTree.get();
-    }
-    TemplateVariant fileName() const
-    {
-      return "modules";
-    }
-    TemplateVariant relPath() const
-    {
-      return "";
-    }
-    TemplateVariant highlight() const
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant tree() const                 { return TemplateVariant(m_moduleTree); }
+    TemplateVariant fileName() const             { return "modules"; }
+    TemplateVariant relPath() const              { return ""; }
+    TemplateVariant highlight() const            { return "modules"; }
+    TemplateVariant subhighlight() const         { return ""; }
+    TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
+    TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
+    TemplateVariant title() const                { return theTranslator->trModules(); }
+  private:
+    int createMaxDepth() const
     {
-      return "modules";
+      return computeMaxDepth(m_moduleTree);
     }
-    TemplateVariant subhighlight() const
+    int createPreferredDepth() const
     {
-      return "";
+      return computePreferredDepth(m_moduleTree,m_maxDepth.get(this));
     }
-    TemplateVariant title() const
+    TemplateListIntfPtr m_moduleTree;
+    CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
+    CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
+    static const PropertyMap<ModuleTreeContext::Private> s_inst;
+};
+
+//%% struct ModuleTree: tree of modules
+//%% {
+const PropertyMap<ModuleTreeContext::Private> ModuleTreeContext::Private::s_inst {
+  {  "tree",          &Private::tree },
+  {  "fileName",      &Private::fileName },
+  {  "relPath",       &Private::relPath },
+  {  "highlight",     &Private::highlight },
+  {  "subhighlight",  &Private::subhighlight },
+  {  "title",         &Private::title },
+  {  "preferredDepth",&Private::preferredDepth },
+  {  "maxDepth",      &Private::maxDepth }
+};
+//%% }
+
+//PropertyMapper<ModuleTreeContext::Private> ModuleTreeContext::Private::s_inst;
+
+ModuleTreeContext::ModuleTreeContext() : p(std::make_unique<Private>())
+{
+}
+
+ModuleTreeContext::~ModuleTreeContext()
+{
+}
+
+TemplateVariant ModuleTreeContext::get(const QCString &name) const
+{
+  return p->get(name);
+}
+
+StringVector ModuleTreeContext::fields() const
+{
+  return p->fields();
+}
+
+//------------------------------------------------------------------------
+
+class ExampleTreeContext::Private
+{
+  public:
+    Private()
     {
-      return theTranslator->trModules();
+      m_exampleTree = NestingContext::alloc(0,ContextTreeType::Example,0);
+      auto ctx = std::dynamic_pointer_cast<NestingContext>(m_exampleTree);
+      ClassDefSet visitedClasses;
+      // Add pages
+      ctx->addPages(*Doxygen::exampleLinkedMap,TRUE,visitedClasses);
     }
-    TemplateVariant maxDepth() const
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant tree() const                 { return TemplateVariant(m_exampleTree); }
+    TemplateVariant fileName() const             { return "examples"; }
+    TemplateVariant relPath() const              { return ""; }
+    TemplateVariant highlight() const            { return "examples"; }
+    TemplateVariant subhighlight() const         { return ""; }
+    TemplateVariant maxDepth() const             { return m_maxDepth.get(this); }
+    TemplateVariant preferredDepth() const       { return m_preferredDepth.get(this); }
+    TemplateVariant title() const                { return theTranslator->trExamples(); }
+
+  private:
+    int createMaxDepth() const
     {
-      if (!m_cache.maxDepthComputed)
-      {
-        m_cache.maxDepth = computeMaxDepth(m_moduleTree.get());
-        m_cache.maxDepthComputed=TRUE;
-      }
-      return m_cache.maxDepth;
+      return computeMaxDepth(m_exampleTree);
     }
-    TemplateVariant preferredDepth() const
+    int createPreferredDepth() const
     {
-      if (!m_cache.preferredDepthComputed)
-      {
-        m_cache.preferredDepth = computePreferredDepth(m_moduleTree.get(),maxDepth().toInt());
-        m_cache.preferredDepthComputed=TRUE;
-      }
-      return m_cache.preferredDepth;
+      return computePreferredDepth(m_exampleTree,m_maxDepth.get(this));
     }
-  private:
-    SharedPtr<NestingContext> m_moduleTree;
-    struct Cachable
-    {
-      Cachable() : maxDepth(0), maxDepthComputed(FALSE),
-                   preferredDepth(0), preferredDepthComputed(FALSE) {}
-      int   maxDepth;
-      bool  maxDepthComputed;
-      int   preferredDepth;
-      bool  preferredDepthComputed;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<ModuleTreeContext::Private> s_inst;
+    TemplateListIntfPtr m_exampleTree;
+    CachedItem<int, Private, &Private::createMaxDepth>       m_maxDepth;
+    CachedItem<int, Private, &Private::createPreferredDepth> m_preferredDepth;
+    static const PropertyMap<ExampleTreeContext::Private> s_inst;
+};
+
+//%% struct ExampleTree: tree of examples page
+//%% {
+const PropertyMap<ExampleTreeContext::Private> ExampleTreeContext::Private::s_inst {
+  {  "tree",          &Private::tree },
+  {  "fileName",      &Private::fileName },
+  {  "relPath",       &Private::relPath },
+  {  "highlight",     &Private::highlight },
+  {  "subhighlight",  &Private::subhighlight },
+  {  "title",         &Private::title },
+  {  "preferredDepth",&Private::preferredDepth },
+  {  "maxDepth",      &Private::maxDepth }
 };
 //%% }
 
-PropertyMapper<ModuleTreeContext::Private> ModuleTreeContext::Private::s_inst;
 
-ModuleTreeContext::ModuleTreeContext() : RefCountedContext("ModuleTreeContext")
+ExampleTreeContext::ExampleTreeContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
-ModuleTreeContext::~ModuleTreeContext()
+ExampleTreeContext::~ExampleTreeContext()
 {
-  delete p;
 }
 
-TemplateVariant ModuleTreeContext::get(const QCString &name) const
+TemplateVariant ExampleTreeContext::get(const QCString &name) const
 {
   return p->get(name);
 }
 
-StringVector ModuleTreeContext::fields() const
+StringVector ExampleTreeContext::fields() const
 {
   return p->fields();
 }
 
+
 //------------------------------------------------------------------------
 
-//%% struct NavPathElem: list of examples page
-//%% {
 class NavPathElemContext::Private
 {
   public:
-    Private(const Definition *def) : m_def(def)
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("isLinkable",       &Private::isLinkable);
-        s_inst.addProperty("fileName",         &Private::fileName);
-        s_inst.addProperty("anchor",           &Private::anchor);
-        s_inst.addProperty("text",             &Private::text);
-        s_inst.addProperty("isReference",      &Private::isReference);
-        s_inst.addProperty("externalReference",&Private::externalReference);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant isLinkable() const
-    {
-      return m_def->isLinkable();
-    }
-    TemplateVariant anchor() const
-    {
-      return m_def->anchor();
-    }
-    TemplateVariant fileName() const
-    {
-      return m_def->getOutputFileBase();
-    }
+    Private(const Definition *def) : m_def(def) {}
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant isLinkable() const           { return m_def->isLinkable(); }
+    TemplateVariant anchor() const               { return m_def->anchor(); }
+    TemplateVariant fileName() const             { return m_def->getOutputFileBase(); }
+    TemplateVariant isReference() const          { return m_def->isReference(); }
+    TemplateVariant externalReference() const    { return m_def->externalReference(relPathAsString()); }
     TemplateVariant text() const
     {
       Definition::DefType type = m_def->definitionType();
@@ -8436,35 +7022,35 @@ class NavPathElemContext::Private
       }
       return text;
     }
-    TemplateVariant isReference() const
-    {
-      return m_def->isReference();
-    }
     QCString relPathAsString() const
     {
       static bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
       return createSubdirs ? QCString("../../") : QCString("");
     }
-    TemplateVariant externalReference() const
-    {
-      return m_def->externalReference(relPathAsString());
-    }
   private:
     const Definition *m_def;
-    static PropertyMapper<NavPathElemContext::Private> s_inst;
+    static const PropertyMap<NavPathElemContext::Private> s_inst;
+};
+
+//%% struct NavPathElem: list of examples page
+//%% {
+const PropertyMap<NavPathElemContext::Private> NavPathElemContext::Private::s_inst {
+  {  "isLinkable",       &Private::isLinkable },
+  {  "fileName",         &Private::fileName },
+  {  "anchor",           &Private::anchor },
+  {  "text",             &Private::text },
+  {  "isReference",      &Private::isReference },
+  {  "externalReference",&Private::externalReference }
 };
 //%% }
 
-PropertyMapper<NavPathElemContext::Private> NavPathElemContext::Private::s_inst;
 
-NavPathElemContext::NavPathElemContext(const Definition *def) : RefCountedContext("NavPathElemContext")
+NavPathElemContext::NavPathElemContext(const Definition *def) : p(std::make_unique<Private>(def))
 {
-  p = new Private(def);
 }
 
 NavPathElemContext::~NavPathElemContext()
 {
-  delete p;
 }
 
 TemplateVariant NavPathElemContext::get(const QCString &name) const
@@ -8479,270 +7065,98 @@ StringVector NavPathElemContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct ExampleList: list of examples page
-//%% {
-class ExampleTreeContext::Private
+class GlobalsIndexContext::Private
 {
   public:
-    Private()
-    {
-      m_exampleTree.reset(NestingContext::alloc(0,ContextTreeType::Example,0));
-      ClassDefSet visitedClasses;
-      // Add pages
-      m_exampleTree->addPages(*Doxygen::exampleLinkedMap,TRUE,visitedClasses);
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
 
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("tree",          &Private::tree);
-        s_inst.addProperty("fileName",      &Private::fileName);
-        s_inst.addProperty("relPath",       &Private::relPath);
-        s_inst.addProperty("highlight",     &Private::highlight);
-        s_inst.addProperty("subhighlight",  &Private::subhighlight);
-        s_inst.addProperty("title",         &Private::title);
-        s_inst.addProperty("preferredDepth",&Private::preferredDepth);
-        s_inst.addProperty("maxDepth",      &Private::maxDepth);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant tree() const
-    {
-      return m_exampleTree.get();
-    }
-    TemplateVariant fileName() const
-    {
-      return "examples";
-    }
-    TemplateVariant relPath() const
-    {
-      return "";
-    }
-    TemplateVariant highlight() const
-    {
-      return "examples";
-    }
-    TemplateVariant subhighlight() const
-    {
-      return "";
-    }
-    TemplateVariant title() const
-    {
-      return theTranslator->trExamples();
-    }
-    TemplateVariant maxDepth() const
-    {
-      if (!m_cache.maxDepthComputed)
-      {
-        m_cache.maxDepth = computeMaxDepth(m_exampleTree.get());
-        m_cache.maxDepthComputed=TRUE;
-      }
-      return m_cache.maxDepth;
-    }
-    TemplateVariant preferredDepth() const
-    {
-      if (!m_cache.preferredDepthComputed)
-      {
-        m_cache.preferredDepth = computePreferredDepth(m_exampleTree.get(),maxDepth().toInt());
-        m_cache.preferredDepthComputed=TRUE;
-      }
-      return m_cache.preferredDepth;
-    }
   private:
-    SharedPtr<NestingContext> m_exampleTree;
-    struct Cachable
-    {
-      Cachable() : maxDepth(0), maxDepthComputed(FALSE),
-                   preferredDepth(0), preferredDepthComputed(FALSE) {}
-      int   maxDepth;
-      bool  maxDepthComputed;
-      int   preferredDepth;
-      bool  preferredDepthComputed;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<ExampleTreeContext::Private> s_inst;
-};
-//%% }
-
-PropertyMapper<ExampleTreeContext::Private> ExampleTreeContext::Private::s_inst;
-
-ExampleTreeContext::ExampleTreeContext() : RefCountedContext("ExampleTreeContext")
-{
-  p = new Private;
-}
+    // Property getters
+    TemplateVariant all() const                  { return m_all.get(this); }
+    TemplateVariant functions() const            { return m_functions.get(this); }
+    TemplateVariant variables() const            { return m_variables.get(this); }
+    TemplateVariant typedefs() const             { return m_typedefs.get(this); }
+    TemplateVariant enums() const                { return m_enums.get(this); }
+    TemplateVariant enumValues() const           { return m_enumValues.get(this); }
+    TemplateVariant macros() const               { return m_macros.get(this); }
+    TemplateVariant properties() const           { return FALSE; }
+    TemplateVariant events() const               { return FALSE; }
+    TemplateVariant related() const              { return FALSE; }
+    TemplateVariant fileName() const             { return "globals"; }
+    TemplateVariant relPath() const              { return ""; }
+    TemplateVariant highlight() const            { return "files"; }
+    TemplateVariant subhighlight() const         { return "filemembers"; }
+    TemplateVariant title() const                { return theTranslator->trFileMembers(); }
 
-ExampleTreeContext::~ExampleTreeContext()
-{
-  delete p;
-}
-
-TemplateVariant ExampleTreeContext::get(const QCString &name) const
-{
-  return p->get(name);
-}
-
-StringVector ExampleTreeContext::fields() const
-{
-  return p->fields();
-}
-
-//------------------------------------------------------------------------
-
-//%% struct GlobalsIndex: list of examples page
-//%% {
-class GlobalsIndexContext::Private
-{
-  public:
-    Private()
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("all",         &Private::all);
-        s_inst.addProperty("functions",   &Private::functions);
-        s_inst.addProperty("variables",   &Private::variables);
-        s_inst.addProperty("typedefs",    &Private::typedefs);
-        s_inst.addProperty("enums",       &Private::enums);
-        s_inst.addProperty("enumValues",  &Private::enumValues);
-        s_inst.addProperty("macros",      &Private::macros);
-        s_inst.addProperty("properties",  &Private::properties);
-        s_inst.addProperty("events",      &Private::events);
-        s_inst.addProperty("related",     &Private::related);
-        s_inst.addProperty("fileName",    &Private::fileName);
-        s_inst.addProperty("relPath",     &Private::relPath);
-        s_inst.addProperty("highlight",   &Private::highlight);
-        s_inst.addProperty("subhighlight",&Private::subhighlight);
-        s_inst.addProperty("title",       &Private::title);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    typedef bool (MemberDef::*MemberFunc)() const;
-    TemplateVariant getMembersFiltered(SharedPtr<TemplateList> &listRef,MemberFunc filter) const
+  private:
+    using MemberFilter = bool (MemberDef::*)() const;
+    TemplateVariant createMembersFiltered(MemberFilter filter) const
     {
-      if (!listRef)
+      TemplateVariantList list;
+      for (const auto &mn : *Doxygen::functionNameLinkedMap)
       {
-        TemplateList *list = TemplateList::alloc();
-        for (const auto &mn : *Doxygen::functionNameLinkedMap)
+        for (const auto &md : *mn)
         {
-          for (const auto &md : *mn)
+          const FileDef *fd=md->getFileDef();
+          if (fd && fd->isLinkableInProject() &&
+              !md->name().isEmpty() && !md->getNamespaceDef() && md->isLinkableInProject())
           {
-            const FileDef *fd=md->getFileDef();
-            if (fd && fd->isLinkableInProject() &&
-                !md->name().isEmpty() && !md->getNamespaceDef() && md->isLinkableInProject())
+            if (filter==0 || (md.get()->*filter)())
             {
-              if (filter==0 || (md.get()->*filter)())
-              {
-                list->append(MemberContext::alloc(md.get()));
-              }
+              list.push_back(MemberContext::alloc(md.get()));
             }
           }
         }
-        listRef.reset(list);
       }
-      return listRef.get();
-    }
-    TemplateVariant all() const
-    {
-      return getMembersFiltered(m_cache.all,0);
-    }
-    TemplateVariant functions() const
-    {
-      return getMembersFiltered(m_cache.functions,&MemberDef::isFunction);
-    }
-    TemplateVariant variables() const
-    {
-      return getMembersFiltered(m_cache.variables,&MemberDef::isVariable);
-    }
-    TemplateVariant typedefs() const
-    {
-      return getMembersFiltered(m_cache.typedefs,&MemberDef::isTypedef);
-    }
-    TemplateVariant enums() const
-    {
-      return getMembersFiltered(m_cache.enums,&MemberDef::isEnumerate);
-    }
-    TemplateVariant enumValues() const
-    {
-      return getMembersFiltered(m_cache.enumValues,&MemberDef::isEnumValue);
-    }
-    TemplateVariant macros() const
-    {
-      return getMembersFiltered(m_cache.macros,&MemberDef::isDefine);
-    }
-    TemplateVariant properties() const
-    {
-      return FALSE;
-    }
-    TemplateVariant events() const
-    {
-      return FALSE;
-    }
-    TemplateVariant related() const
-    {
-      return FALSE;
-    }
-    TemplateVariant fileName() const
-    {
-      return "globals";
-    }
-    TemplateVariant relPath() const
-    {
-      return "";
-    }
-    TemplateVariant highlight() const
-    {
-      return "files";
-    }
-    TemplateVariant subhighlight() const
-    {
-      return "filemembers";
-    }
-    TemplateVariant title() const
-    {
-      return theTranslator->trFileMembers();
-    }
-  private:
-    struct Cachable
-    {
-      Cachable() {}
-      SharedPtr<TemplateList> all;
-      SharedPtr<TemplateList> functions;
-      SharedPtr<TemplateList> variables;
-      SharedPtr<TemplateList> typedefs;
-      SharedPtr<TemplateList> enums;
-      SharedPtr<TemplateList> enumValues;
-      SharedPtr<TemplateList> macros;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<GlobalsIndexContext::Private> s_inst;
+      return TemplateImmutableList::alloc(list);
+    }
+    TemplateVariant createAll() const        { return createMembersFiltered(0); }
+    TemplateVariant createFunctions() const  { return createMembersFiltered(&MemberDef::isFunction); }
+    TemplateVariant createVariables() const  { return createMembersFiltered(&MemberDef::isVariable); }
+    TemplateVariant createTypedefs() const   { return createMembersFiltered(&MemberDef::isTypedef); }
+    TemplateVariant createEnums() const      { return createMembersFiltered(&MemberDef::isEnumerate); }
+    TemplateVariant createEnumValues() const { return createMembersFiltered(&MemberDef::isEnumValue); }
+    TemplateVariant createMacros() const     { return createMembersFiltered(&MemberDef::isDefine); }
+
+    CachedItem<TemplateVariant,  Private, &Private::createAll>        m_all;
+    CachedItem<TemplateVariant,  Private, &Private::createFunctions>  m_functions;
+    CachedItem<TemplateVariant,  Private, &Private::createVariables>  m_variables;
+    CachedItem<TemplateVariant,  Private, &Private::createTypedefs>   m_typedefs;
+    CachedItem<TemplateVariant,  Private, &Private::createEnums>      m_enums;
+    CachedItem<TemplateVariant,  Private, &Private::createEnumValues> m_enumValues;
+    CachedItem<TemplateVariant,  Private, &Private::createMacros>     m_macros;
+    static const PropertyMap<GlobalsIndexContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<GlobalsIndexContext::Private> GlobalsIndexContext::Private::s_inst;
+//%% struct GlobalsIndex: list of examples page
+//%% {
+const PropertyMap<GlobalsIndexContext::Private> GlobalsIndexContext::Private::s_inst {
+  {  "all",         &Private::all },
+  {  "functions",   &Private::functions },
+  {  "variables",   &Private::variables },
+  {  "typedefs",    &Private::typedefs },
+  {  "enums",       &Private::enums },
+  {  "enumValues",  &Private::enumValues },
+  {  "macros",      &Private::macros },
+  {  "properties",  &Private::properties },
+  {  "events",      &Private::events },
+  {  "related",     &Private::related },
+  {  "fileName",    &Private::fileName },
+  {  "relPath",     &Private::relPath },
+  {  "highlight",   &Private::highlight },
+  {  "subhighlight",&Private::subhighlight },
+  {  "title",       &Private::title }
+};
+//%% }
 
-GlobalsIndexContext::GlobalsIndexContext() : RefCountedContext("GlobalsIndexContext")
+GlobalsIndexContext::GlobalsIndexContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 GlobalsIndexContext::~GlobalsIndexContext()
 {
-  delete p;
 }
 
 TemplateVariant GlobalsIndexContext::get(const QCString &name) const
@@ -8758,156 +7172,103 @@ StringVector GlobalsIndexContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct ClassMembersIndex: list of examples page
-//%% {
 class ClassMembersIndexContext::Private
 {
   public:
-    Private()
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("all",         &Private::all);
-        s_inst.addProperty("functions",   &Private::functions);
-        s_inst.addProperty("variables",   &Private::variables);
-        s_inst.addProperty("typedefs",    &Private::typedefs);
-        s_inst.addProperty("enums",       &Private::enums);
-        s_inst.addProperty("enumValues",  &Private::enumValues);
-        s_inst.addProperty("macros",      &Private::macros);
-        s_inst.addProperty("properties",  &Private::properties);
-        s_inst.addProperty("events",      &Private::events);
-        s_inst.addProperty("related",     &Private::related);
-        s_inst.addProperty("fileName",    &Private::fileName);
-        s_inst.addProperty("relPath",     &Private::relPath);
-        s_inst.addProperty("highlight",   &Private::highlight);
-        s_inst.addProperty("subhighlight",&Private::subhighlight);
-        s_inst.addProperty("title",       &Private::title);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    typedef bool (MemberDef::*MemberFunc)() const;
-    TemplateVariant getMembersFiltered(SharedPtr<TemplateList> &listRef,MemberFunc filter) const
-    {
-      if (!listRef)
-      {
-        TemplateList *list = TemplateList::alloc();
-        for (const auto &mn : *Doxygen::memberNameLinkedMap)
-        {
-          for (const auto &md : *mn)
-          {
-            const ClassDef *cd = md->getClassDef();
-            if (cd && cd->isLinkableInProject() && cd->templateMaster()==0 &&
-                md->isLinkableInProject() && !md->name().isEmpty())
-            {
-              if (filter==0 || (md.get()->*filter)())
-              {
-                list->append(MemberContext::alloc(md.get()));
-              }
-            }
-          }
-        }
-        listRef.reset(list);
-      }
-      return listRef.get();
-    }
-    TemplateVariant all() const
-    {
-      return getMembersFiltered(m_cache.all,&MemberDef::isNotFriend);
-    }
-    TemplateVariant functions() const
-    {
-      return getMembersFiltered(m_cache.functions,&MemberDef::isFunctionOrSignalSlot);
-    }
-    TemplateVariant variables() const
-    {
-      return getMembersFiltered(m_cache.variables,&MemberDef::isVariable);
-    }
-    TemplateVariant typedefs() const
-    {
-      return getMembersFiltered(m_cache.typedefs,&MemberDef::isTypedef);
-    }
-    TemplateVariant enums() const
-    {
-      return getMembersFiltered(m_cache.enums,&MemberDef::isEnumerate);
-    }
-    TemplateVariant enumValues() const
-    {
-      return getMembersFiltered(m_cache.enumValues,&MemberDef::isEnumValue);
-    }
-    TemplateVariant macros() const
-    {
-      return FALSE;
-    }
-    TemplateVariant properties() const
-    {
-      return getMembersFiltered(m_cache.properties,&MemberDef::isProperty);
-    }
-    TemplateVariant events() const
-    {
-      return getMembersFiltered(m_cache.events,&MemberDef::isEvent);
-    }
-    TemplateVariant related() const
-    {
-      return getMembersFiltered(m_cache.related,&MemberDef::isRelated);
-    }
-    TemplateVariant fileName() const
-    {
-      return "functions";
-    }
-    TemplateVariant relPath() const
-    {
-      return "";
-    }
-    TemplateVariant highlight() const
-    {
-      return "classes";
-    }
-    TemplateVariant subhighlight() const
-    {
-      return "classmembers";
-    }
-    TemplateVariant title() const
-    {
-      return theTranslator->trCompoundMembers();
-    }
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant all() const                  { return m_all.get(this); }
+    TemplateVariant functions() const            { return m_functions.get(this); }
+    TemplateVariant variables() const            { return m_variables.get(this); }
+    TemplateVariant typedefs() const             { return m_typedefs.get(this); }
+    TemplateVariant enums() const                { return m_enums.get(this); }
+    TemplateVariant enumValues() const           { return m_enumValues.get(this); }
+    TemplateVariant macros() const               { return FALSE; }
+    TemplateVariant properties() const           { return m_properties.get(this); }
+    TemplateVariant events() const               { return m_events.get(this); }
+    TemplateVariant related() const              { return m_related.get(this); }
+    TemplateVariant fileName() const             { return "functions"; }
+    TemplateVariant relPath() const              { return ""; }
+    TemplateVariant highlight() const            { return "classes"; }
+    TemplateVariant subhighlight() const         { return "classmembers"; }
+    TemplateVariant title() const                { return theTranslator->trCompoundMembers(); }
+
   private:
-    struct Cachable
-    {
-      Cachable() {}
-      SharedPtr<TemplateList> all;
-      SharedPtr<TemplateList> functions;
-      SharedPtr<TemplateList> variables;
-      SharedPtr<TemplateList> typedefs;
-      SharedPtr<TemplateList> enums;
-      SharedPtr<TemplateList> enumValues;
-      SharedPtr<TemplateList> properties;
-      SharedPtr<TemplateList> events;
-      SharedPtr<TemplateList> related;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<ClassMembersIndexContext::Private> s_inst;
+    using MemberFilter = bool (MemberDef::*)() const;
+    TemplateVariant createMembersFiltered(MemberFilter filter) const
+    {
+      TemplateVariantList list;
+      for (const auto &mn : *Doxygen::memberNameLinkedMap)
+      {
+        for (const auto &md : *mn)
+        {
+          const ClassDef *cd = md->getClassDef();
+          if (cd && cd->isLinkableInProject() && cd->templateMaster()==0 &&
+              md->isLinkableInProject() && !md->name().isEmpty())
+          {
+            if (filter==0 || (md.get()->*filter)())
+            {
+              list.push_back(MemberContext::alloc(md.get()));
+            }
+          }
+        }
+      }
+      return TemplateImmutableList::alloc(list);
+    }
+    TemplateVariant createAll() const        { return createMembersFiltered(&MemberDef::isNotFriend); }
+    TemplateVariant createFunctions() const  { return createMembersFiltered(&MemberDef::isFunctionOrSignalSlot); }
+    TemplateVariant createVariables() const  { return createMembersFiltered(&MemberDef::isVariable); }
+    TemplateVariant createTypedefs() const   { return createMembersFiltered(&MemberDef::isTypedef); }
+    TemplateVariant createEnums() const      { return createMembersFiltered(&MemberDef::isEnumerate); }
+    TemplateVariant createEnumValues() const { return createMembersFiltered(&MemberDef::isEnumValue); }
+    TemplateVariant createProperties() const { return createMembersFiltered(&MemberDef::isProperty); }
+    TemplateVariant createEvents() const     { return createMembersFiltered(&MemberDef::isEvent); }
+    TemplateVariant createRelated() const    { return createMembersFiltered(&MemberDef::isRelated); }
+
+    CachedItem<TemplateVariant,  Private, &Private::createAll>        m_all;
+    CachedItem<TemplateVariant,  Private, &Private::createFunctions>  m_functions;
+    CachedItem<TemplateVariant,  Private, &Private::createVariables>  m_variables;
+    CachedItem<TemplateVariant,  Private, &Private::createTypedefs>   m_typedefs;
+    CachedItem<TemplateVariant,  Private, &Private::createEnums>      m_enums;
+    CachedItem<TemplateVariant,  Private, &Private::createEnumValues> m_enumValues;
+    CachedItem<TemplateVariant,  Private, &Private::createProperties> m_properties;
+    CachedItem<TemplateVariant,  Private, &Private::createEvents>     m_events;
+    CachedItem<TemplateVariant,  Private, &Private::createRelated>    m_related;
+    static const PropertyMap<ClassMembersIndexContext::Private> s_inst;
+};
+
+//%% struct ClassMembersIndex: list of examples page
+//%% {
+const PropertyMap<ClassMembersIndexContext::Private> ClassMembersIndexContext::Private::s_inst {
+  {  "all",         &Private::all },
+  {  "functions",   &Private::functions },
+  {  "variables",   &Private::variables },
+  {  "typedefs",    &Private::typedefs },
+  {  "enums",       &Private::enums },
+  {  "enumValues",  &Private::enumValues },
+  {  "macros",      &Private::macros },
+  {  "properties",  &Private::properties },
+  {  "events",      &Private::events },
+  {  "related",     &Private::related },
+  {  "fileName",    &Private::fileName },
+  {  "relPath",     &Private::relPath },
+  {  "highlight",   &Private::highlight },
+  {  "subhighlight",&Private::subhighlight },
+  {  "title",       &Private::title }
 };
 //%% }
 
-PropertyMapper<ClassMembersIndexContext::Private> ClassMembersIndexContext::Private::s_inst;
 
-ClassMembersIndexContext::ClassMembersIndexContext() : RefCountedContext("ClassMembersIndexContext")
+ClassMembersIndexContext::ClassMembersIndexContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 ClassMembersIndexContext::~ClassMembersIndexContext()
 {
-  delete p;
 }
 
 TemplateVariant ClassMembersIndexContext::get(const QCString &name) const
@@ -8922,153 +7283,98 @@ StringVector ClassMembersIndexContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct NamespaceMembersIndex: list of examples page
-//%% {
 class NamespaceMembersIndexContext::Private
 {
   public:
-    Private()
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("all",         &Private::all);
-        s_inst.addProperty("functions",   &Private::functions);
-        s_inst.addProperty("variables",   &Private::variables);
-        s_inst.addProperty("typedefs",    &Private::typedefs);
-        s_inst.addProperty("enums",       &Private::enums);
-        s_inst.addProperty("enumValues",  &Private::enumValues);
-        s_inst.addProperty("macros",      &Private::macros);
-        s_inst.addProperty("properties",  &Private::properties);
-        s_inst.addProperty("events",      &Private::events);
-        s_inst.addProperty("related",     &Private::related);
-        s_inst.addProperty("fileName",    &Private::fileName);
-        s_inst.addProperty("relPath",     &Private::relPath);
-        s_inst.addProperty("highlight",   &Private::highlight);
-        s_inst.addProperty("subhighlight",&Private::subhighlight);
-        s_inst.addProperty("title",       &Private::title);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    typedef bool (MemberDef::*MemberFunc)() const;
-    TemplateVariant getMembersFiltered(SharedPtr<TemplateList> &listRef,MemberFunc filter) const
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant all() const                  { return m_all.get(this); }
+    TemplateVariant functions() const            { return m_functions.get(this); }
+    TemplateVariant variables() const            { return m_variables.get(this); }
+    TemplateVariant typedefs() const             { return m_typedefs.get(this); }
+    TemplateVariant enums() const                { return m_enums.get(this); }
+    TemplateVariant enumValues() const           { return m_enumValues.get(this); }
+    TemplateVariant macros() const               { return FALSE; }
+    TemplateVariant properties() const           { return FALSE; }
+    TemplateVariant events() const               { return FALSE; }
+    TemplateVariant related() const              { return FALSE; }
+    TemplateVariant fileName() const             { return "namespacemembers"; }
+    TemplateVariant relPath() const              { return ""; }
+    TemplateVariant highlight() const            { return "namespaces"; }
+    TemplateVariant subhighlight() const         { return "namespacemembers"; }
+    TemplateVariant title() const                { return theTranslator->trNamespaceMembers(); }
+
+  private:
+    using MemberFilter = bool (MemberDef::*)() const;
+    TemplateVariant createMembersFiltered(MemberFilter filter) const
     {
-      if (!listRef)
+      TemplateVariantList list;
+      for (const auto &mn : *Doxygen::functionNameLinkedMap)
       {
-        TemplateList *list = TemplateList::alloc();
-        for (const auto &mn : *Doxygen::functionNameLinkedMap)
+        for (const auto &md : *mn)
         {
-          for (const auto &md : *mn)
+          const NamespaceDef *nd=md->getNamespaceDef();
+          if (nd && nd->isLinkableInProject() &&
+              !md->name().isEmpty() && md->isLinkableInProject())
           {
-            const NamespaceDef *nd=md->getNamespaceDef();
-            if (nd && nd->isLinkableInProject() &&
-                !md->name().isEmpty() && md->isLinkableInProject())
+            if (filter==0 || (md.get()->*filter)())
             {
-              if (filter==0 || (md.get()->*filter)())
-              {
-                list->append(MemberContext::alloc(md.get()));
-              }
+              list.push_back(MemberContext::alloc(md.get()));
             }
           }
         }
-        listRef.reset(list);
       }
-      return listRef.get();
-    }
-    TemplateVariant all() const
-    {
-      return getMembersFiltered(m_cache.all,0);
-    }
-    TemplateVariant functions() const
-    {
-      return getMembersFiltered(m_cache.functions,&MemberDef::isFunction);
-    }
-    TemplateVariant variables() const
-    {
-      return getMembersFiltered(m_cache.variables,&MemberDef::isVariable);
-    }
-    TemplateVariant typedefs() const
-    {
-      return getMembersFiltered(m_cache.typedefs,&MemberDef::isTypedef);
-    }
-    TemplateVariant enums() const
-    {
-      return getMembersFiltered(m_cache.enums,&MemberDef::isEnumerate);
-    }
-    TemplateVariant enumValues() const
-    {
-      return getMembersFiltered(m_cache.enumValues,&MemberDef::isEnumValue);
-    }
-    TemplateVariant macros() const
-    {
-      return FALSE;
-    }
-    TemplateVariant properties() const
-    {
-      return FALSE;
-    }
-    TemplateVariant events() const
-    {
-      return FALSE;
-    }
-    TemplateVariant related() const
-    {
-      return FALSE;
-    }
-    TemplateVariant fileName() const
-    {
-      return "namespacemembers";
-    }
-    TemplateVariant relPath() const
-    {
-      return "";
-    }
-    TemplateVariant highlight() const
-    {
-      return "namespaces";
-    }
-    TemplateVariant subhighlight() const
-    {
-      return "namespacemembers";
+      return TemplateImmutableList::alloc(list);
     }
-    TemplateVariant title() const
-    {
-      return theTranslator->trNamespaceMembers();
-    }
-  private:
-    struct Cachable
-    {
-      Cachable() {}
-      SharedPtr<TemplateList> all;
-      SharedPtr<TemplateList> functions;
-      SharedPtr<TemplateList> variables;
-      SharedPtr<TemplateList> typedefs;
-      SharedPtr<TemplateList> enums;
-      SharedPtr<TemplateList> enumValues;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<NamespaceMembersIndexContext::Private> s_inst;
+
+    TemplateVariant createAll() const        { return createMembersFiltered(0); }
+    TemplateVariant createFunctions() const  { return createMembersFiltered(&MemberDef::isFunction); }
+    TemplateVariant createVariables() const  { return createMembersFiltered(&MemberDef::isVariable); }
+    TemplateVariant createTypedefs() const   { return createMembersFiltered(&MemberDef::isTypedef); }
+    TemplateVariant createEnums() const      { return createMembersFiltered(&MemberDef::isEnumerate); }
+    TemplateVariant createEnumValues() const { return createMembersFiltered(&MemberDef::isEnumValue); }
+
+    CachedItem<TemplateVariant,  Private, &Private::createAll>        m_all;
+    CachedItem<TemplateVariant,  Private, &Private::createFunctions>  m_functions;
+    CachedItem<TemplateVariant,  Private, &Private::createVariables>  m_variables;
+    CachedItem<TemplateVariant,  Private, &Private::createTypedefs>   m_typedefs;
+    CachedItem<TemplateVariant,  Private, &Private::createEnums>      m_enums;
+    CachedItem<TemplateVariant,  Private, &Private::createEnumValues> m_enumValues;
+    static const PropertyMap<NamespaceMembersIndexContext::Private> s_inst;
+};
+
+//%% struct NamespaceMembersIndex: list of examples page
+//%% {
+const PropertyMap<NamespaceMembersIndexContext::Private> NamespaceMembersIndexContext::Private::s_inst {
+  {  "all",         &Private::all },
+  {  "functions",   &Private::functions },
+  {  "variables",   &Private::variables },
+  {  "typedefs",    &Private::typedefs },
+  {  "enums",       &Private::enums },
+  {  "enumValues",  &Private::enumValues },
+  {  "macros",      &Private::macros },
+  {  "properties",  &Private::properties },
+  {  "events",      &Private::events },
+  {  "related",     &Private::related },
+  {  "fileName",    &Private::fileName },
+  {  "relPath",     &Private::relPath },
+  {  "highlight",   &Private::highlight },
+  {  "subhighlight",&Private::subhighlight },
+  {  "title",       &Private::title }
 };
 //%% }
 
-PropertyMapper<NamespaceMembersIndexContext::Private> NamespaceMembersIndexContext::Private::s_inst;
 
-NamespaceMembersIndexContext::NamespaceMembersIndexContext() : RefCountedContext("NamespaceMembersIndexContext")
+NamespaceMembersIndexContext::NamespaceMembersIndexContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 NamespaceMembersIndexContext::~NamespaceMembersIndexContext()
 {
-  delete p;
 }
 
 TemplateVariant NamespaceMembersIndexContext::get(const QCString &name) const
@@ -9083,29 +7389,22 @@ StringVector NamespaceMembersIndexContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct InheritanceGraph: a connected graph representing part of the overall inheritance tree
-//%% {
 class InheritanceGraphContext::Private
 {
   public:
-    Private(DotGfxHierarchyTable *hierarchy,DotNode *n,int id) : m_hierarchy(hierarchy), m_node(n), m_id(id)
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("graph",&Private::graph);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant graph() const
+    Private(DotGfxHierarchyTablePtr hierarchy,DotNode *n,int id)
+      : m_hierarchy(hierarchy), m_node(n), m_id(id) { }
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant graph() const                { return m_graph.get(this); }
+
+  private:
+    TemplateVariant createGraph() const
     {
       TextStream t;
       static bool haveDot            = Config_getBool(HAVE_DOT);
@@ -9121,24 +7420,26 @@ class InheritanceGraphContext::Private
       }
       return TemplateVariant(t.str().c_str(),TRUE);
     }
-  private:
-    DotGfxHierarchyTable *m_hierarchy;
+    DotGfxHierarchyTablePtr m_hierarchy;
     DotNode *m_node;
+    CachedItem<TemplateVariant,Private,&Private::createGraph> m_graph;
     int m_id;
-    static PropertyMapper<InheritanceGraphContext::Private> s_inst;
+    static const PropertyMap<InheritanceGraphContext::Private> s_inst;
 };
 
-PropertyMapper<InheritanceGraphContext::Private> InheritanceGraphContext::Private::s_inst;
+//%% struct InheritanceGraph: a connected graph representing part of the overall inheritance tree
+//%% {
+const PropertyMap<InheritanceGraphContext::Private> InheritanceGraphContext::Private::s_inst {
+  {  "graph",&Private::graph }
+};
+//%% }
 
-InheritanceGraphContext::InheritanceGraphContext(DotGfxHierarchyTable *hierarchy,DotNode *n,int id)
-   : RefCountedContext("InheritanceGraphContext")
+InheritanceGraphContext::InheritanceGraphContext(DotGfxHierarchyTablePtr hierarchy,DotNode *n,int id) : p(std::make_unique<Private>(hierarchy,n,id))
 {
-  p = new Private(hierarchy,n,id);
 }
 
 InheritanceGraphContext::~InheritanceGraphContext()
 {
-  delete p;
 }
 
 TemplateVariant InheritanceGraphContext::get(const QCString &name) const
@@ -9153,59 +7454,46 @@ StringVector InheritanceGraphContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct InheritanceNode: a class in the inheritance list
-//%% {
 class InheritanceNodeContext::Private
 {
   public:
-    Private(const ClassDef *cd,const QCString &name) : m_classDef(cd), m_name(name)
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("class",&Private::getClass);
-        s_inst.addProperty("name", &Private::name);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant getClass() const
-    {
-      if (!m_classContext)
-      {
-        m_classContext.reset(ClassContext::alloc(m_classDef));
-      }
-      return m_classContext.get();
-    }
-    TemplateVariant name() const
+    Private(const ClassDef *cd,const QCString &name)
+      : m_classDef(cd), m_name(name) {}
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant getClass() const             { return m_classContext.get(this); }
+    TemplateVariant name() const                 { return m_name; }
+
+  private:
+    TemplateVariant createClass() const
     {
-      return m_name;
+      return ClassContext::alloc(m_classDef);
     }
-  private:
     const ClassDef *m_classDef;
-    mutable SharedPtr<ClassContext> m_classContext;
+    CachedItem<TemplateVariant, Private, &Private::createClass> m_classContext;
     QCString m_name;
-    static PropertyMapper<InheritanceNodeContext::Private> s_inst;
+    static const PropertyMap<InheritanceNodeContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<InheritanceNodeContext::Private> InheritanceNodeContext::Private::s_inst;
+//%% struct InheritanceNode: a class in the inheritance list
+//%% {
+const PropertyMap<InheritanceNodeContext::Private> InheritanceNodeContext::Private::s_inst {
+  {  "class",&Private::getClass },
+  {  "name", &Private::name }
+};
+//%% }
 
-InheritanceNodeContext::InheritanceNodeContext(const ClassDef *cd,const QCString &name) : RefCountedContext("InheritanceNodeContext")
+InheritanceNodeContext::InheritanceNodeContext(const ClassDef *cd,const QCString &name) : p(std::make_unique<Private>(cd,name))
 {
-  p = new Private(cd,name);
 }
 
 InheritanceNodeContext::~InheritanceNodeContext()
 {
-  delete p;
 }
 
 TemplateVariant InheritanceNodeContext::get(const QCString &name) const
@@ -9230,9 +7518,8 @@ class InheritanceListContext::Private : public GenericNodeListContext
     }
 };
 
-InheritanceListContext::InheritanceListContext(const BaseClassList &list, bool baseClasses) : RefCountedContext("InheritanceListContext")
+InheritanceListContext::InheritanceListContext(const BaseClassList &list, bool baseClasses) : p(std::make_unique<Private>())
 {
-  p = new Private;
   for (const auto &bcd : list)
   {
     const ClassDef *cd=bcd.classDef;
@@ -9253,7 +7540,6 @@ InheritanceListContext::InheritanceListContext(const BaseClassList &list, bool b
 
 InheritanceListContext::~InheritanceListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -9267,7 +7553,7 @@ TemplateVariant InheritanceListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *InheritanceListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr InheritanceListContext::createIterator() const
 {
   return p->createIterator();
 }
@@ -9284,14 +7570,12 @@ class MemberListContext::Private : public GenericNodeListContext
     }
 };
 
-MemberListContext::MemberListContext() : RefCountedContext("MemberListContext")
+MemberListContext::MemberListContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
-MemberListContext::MemberListContext(const MemberList *list) : RefCountedContext("MemberListContext")
+MemberListContext::MemberListContext(const MemberList *list) : p(std::make_unique<Private>())
 {
-  p = new Private;
   if (list)
   {
     bool details = list->listType()&MemberListType_detailedLists;
@@ -9307,9 +7591,8 @@ MemberListContext::MemberListContext(const MemberList *list) : RefCountedContext
   }
 }
 
-MemberListContext::MemberListContext(const MemberVector &ml) : RefCountedContext("MemberListContext")
+MemberListContext::MemberListContext(const MemberVector &ml) : p(std::make_unique<Private>())
 {
-  p = new Private;
   for (const auto &md : ml)
   {
     p->addMember(md);
@@ -9318,7 +7601,6 @@ MemberListContext::MemberListContext(const MemberVector &ml) : RefCountedContext
 
 MemberListContext::~MemberListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -9332,42 +7614,24 @@ TemplateVariant MemberListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *MemberListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr MemberListContext::createIterator() const
 {
   return p->createIterator();
 }
 
 //------------------------------------------------------------------------
 
-//%% struct MemberInfo: member information
-//%% {
 class MemberInfoContext::Private
 {
   public:
-    Private(const MemberInfo *mi) : m_memberInfo(mi)
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        //%% string protection
-        s_inst.addProperty("protection",    &Private::protection);
-        //%% string virtualness
-        s_inst.addProperty("virtualness",   &Private::virtualness);
-        //%% string ambiguityScope
-        s_inst.addProperty("ambiguityScope",&Private::ambiguityScope);
-        //%% Member member
-        s_inst.addProperty("member",        &Private::member);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
+    Private(const MemberInfo *mi) : m_memberInfo(mi) {}
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
     TemplateVariant protection() const
     {
       switch (m_memberInfo->prot())
@@ -9395,36 +7659,41 @@ class MemberInfoContext::Private
     }
     TemplateVariant member() const
     {
-      if (!m_member && m_memberInfo->memberDef())
-      {
-        m_member.reset(MemberContext::alloc(m_memberInfo->memberDef()));
-      }
-      if (m_member)
-      {
-        return m_member.get();
-      }
-      else
-      {
-        return TemplateVariant(FALSE);
-      }
+      return m_member.get(this);
     }
+
   private:
+    TemplateVariant createMember() const
+    {
+      return m_memberInfo->memberDef() ?
+        TemplateVariant(MemberContext::alloc(m_memberInfo->memberDef())) :
+        TemplateVariant(false);
+    }
     const MemberInfo *m_memberInfo;
-    mutable SharedPtr<MemberContext> m_member;
-    static PropertyMapper<MemberInfoContext::Private> s_inst;
+    CachedItem<TemplateVariant, Private, &Private::createMember> m_member;
+    static const PropertyMap<MemberInfoContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<MemberInfoContext::Private> MemberInfoContext::Private::s_inst;
+//%% struct MemberInfo: member information
+//%% {
+const PropertyMap<MemberInfoContext::Private> MemberInfoContext::Private::s_inst {
+  //%% string protection
+  {  "protection",    &Private::protection },
+  //%% string virtualness
+  {  "virtualness",   &Private::virtualness },
+  //%% string ambiguityScope
+  {  "ambiguityScope",&Private::ambiguityScope },
+  //%% Member member
+  {  "member",        &Private::member }
+};
+//%% }
 
-MemberInfoContext::MemberInfoContext(const MemberInfo *mi) : RefCountedContext("MemberInfoContext")
+MemberInfoContext::MemberInfoContext(const MemberInfo *mi) : p(std::make_unique<Private>(mi))
 {
-  p = new Private(mi);
 }
 
 MemberInfoContext::~MemberInfoContext()
 {
-  delete p;
 }
 
 TemplateVariant MemberInfoContext::get(const QCString &name) const
@@ -9468,15 +7737,12 @@ class AllMembersListContext::Private : public GenericNodeListContext
     }
 };
 
-AllMembersListContext::AllMembersListContext(const MemberNameInfoLinkedMap &ml)
-  : RefCountedContext("AllMembersListContext")
+AllMembersListContext::AllMembersListContext(const MemberNameInfoLinkedMap &ml) : p(std::make_unique<Private>(ml))
 {
-  p = new Private(ml);
 }
 
 AllMembersListContext::~AllMembersListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -9490,121 +7756,79 @@ TemplateVariant AllMembersListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *AllMembersListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr AllMembersListContext::createIterator() const
 {
   return p->createIterator();
 }
 
 //------------------------------------------------------------------------
 
-//%% struct MemberGroupInfo: member group information
-//%% {
 class MemberGroupInfoContext::Private
 {
   public:
-    Private(const Definition *def,const QCString &relPath,const MemberGroup *mg) :
-      m_def(def),
-      m_relPath(relPath),
-      m_memberGroup(mg)
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("members",      &Private::members);
-        s_inst.addProperty("title",        &Private::groupTitle);
-        s_inst.addProperty("subtitle",     &Private::groupSubtitle);
-        s_inst.addProperty("anchor",       &Private::groupAnchor);
-        s_inst.addProperty("memberGroups", &Private::memberGroups);
-        s_inst.addProperty("docs",         &Private::docs);
-        s_inst.addProperty("inherited",    &Private::inherited);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant members() const
-    {
-      if (!m_cache.memberListContext)
-      {
-        m_cache.memberListContext.reset(MemberListContext::alloc(&m_memberGroup->members()));
-      }
-      return m_cache.memberListContext.get();
-    }
-    TemplateVariant groupTitle() const
-    {
-      return m_memberGroup->header();
-    }
-    TemplateVariant groupSubtitle() const
-    {
-      return "";
-    }
-    TemplateVariant groupAnchor() const
-    {
-      return m_memberGroup->anchor();
-    }
-    TemplateVariant memberGroups() const
+    Private(const Definition *def,const QCString &relPath,const MemberGroup *mg)
+      : m_def(def), m_relPath(relPath), m_memberGroup(mg) {}
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant members() const              { return m_members.get(this); }
+    TemplateVariant groupTitle() const           { return m_memberGroup->header(); }
+    TemplateVariant groupSubtitle() const        { return ""; }
+    TemplateVariant groupAnchor() const          { return m_memberGroup->anchor(); }
+    TemplateVariant memberGroups() const         { return m_memberGroups.get(this); }
+    TemplateVariant docs() const                 { return m_docs.get(this); }
+    TemplateVariant inherited() const            { return FALSE; }
+
+  private:
+    TemplateVariant createMembers() const
     {
-      if (!m_cache.memberGroups)
-      {
-        m_cache.memberGroups.reset(MemberGroupListContext::alloc());
-      }
-      return m_cache.memberGroups.get();
+      return MemberListContext::alloc(&m_memberGroup->members());
     }
-    TemplateVariant docs() const
+    TemplateVariant createMemberGroups() const
     {
-      if (!m_cache.docs)
-      {
-        QCString docs = m_memberGroup->documentation();
-        if (!docs.isEmpty())
-        {
-          m_cache.docs.reset(new TemplateVariant(
-                           parseDoc(m_def,"[@name docs]",-1, // TODO store file & line
-                                    m_relPath,
-                                    m_memberGroup->documentation()+"\n",FALSE)));
-        }
-        else
-        {
-          m_cache.docs.reset(new TemplateVariant(""));
-        }
-      }
-      return *m_cache.docs;
+      return MemberGroupListContext::alloc();
     }
-    TemplateVariant inherited() const
+    TemplateVariant createDocs() const
     {
-      return FALSE;
+      return !m_memberGroup->documentation().isEmpty() ?
+          TemplateVariant(parseDoc(m_def,"[@name docs]",-1, // TODO store file & line
+                                   m_relPath,
+                                   m_memberGroup->documentation(),FALSE)) :
+          TemplateVariant("");
     }
-  private:
     const Definition *m_def;
     QCString m_relPath;
     const MemberGroup *m_memberGroup;
-    struct Cachable
-    {
-      SharedPtr<MemberListContext>      memberListContext;
-      SharedPtr<MemberGroupListContext> memberGroups;
-      std::unique_ptr<TemplateVariant>        docs;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<MemberGroupInfoContext::Private> s_inst;
+    CachedItem<TemplateVariant,Private,&Private::createDocs>         m_docs;
+    CachedItem<TemplateVariant,Private,&Private::createMembers>      m_members;
+    CachedItem<TemplateVariant,Private,&Private::createMemberGroups> m_memberGroups;
+    static const PropertyMap<MemberGroupInfoContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<MemberGroupInfoContext::Private> MemberGroupInfoContext::Private::s_inst;
+//%% struct MemberGroupInfo: member group information
+//%% {
+const PropertyMap<MemberGroupInfoContext::Private> MemberGroupInfoContext::Private::s_inst {
+  {  "members",      &Private::members },
+  {  "title",        &Private::groupTitle },
+  {  "subtitle",     &Private::groupSubtitle },
+  {  "anchor",       &Private::groupAnchor },
+  {  "memberGroups", &Private::memberGroups },
+  {  "docs",         &Private::docs },
+  {  "inherited",    &Private::inherited }
+};
+//%% }
 
 MemberGroupInfoContext::MemberGroupInfoContext(const Definition *def,
-       const QCString &relPath,const MemberGroup *mg) : RefCountedContext("MemberGroupInfoContext")
+       const QCString &relPath,const MemberGroup *mg) : p(std::make_unique<Private>(def,relPath,mg))
 {
-  p = new Private(def,relPath,mg);
 }
 
 MemberGroupInfoContext::~MemberGroupInfoContext()
 {
-  delete p;
 }
 
 TemplateVariant MemberGroupInfoContext::get(const QCString &name) const
@@ -9629,23 +7853,20 @@ class MemberGroupListContext::Private : public GenericNodeListContext
     }
 };
 
-MemberGroupListContext::MemberGroupListContext() : RefCountedContext("MemberGroupListContext")
+MemberGroupListContext::MemberGroupListContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
-MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupRefList &list) : RefCountedContext("MemberGroupListContext")
+MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupRefList &list) : p(std::make_unique<Private>())
 {
-  p = new Private;
   for (const auto &mg : list)
   {
     p->addMemberGroup(def,relPath,mg);
   }
 }
 
-MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupList &list,bool subGrouping) : RefCountedContext("MemberGroupListContext")
+MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupList &list,bool subGrouping) : p(std::make_unique<Private>())
 {
-  p = new Private;
   for (const auto &mg : list)
   {
     if (!mg->allMembersInSameSection() || !subGrouping)
@@ -9657,7 +7878,6 @@ MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCStr
 
 MemberGroupListContext::~MemberGroupListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -9671,7 +7891,7 @@ TemplateVariant MemberGroupListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *MemberGroupListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr MemberGroupListContext::createIterator() const
 {
   return p->createIterator();
 }
@@ -9679,113 +7899,81 @@ TemplateListIntf::ConstIterator *MemberGroupListContext::createIterator() const
 
 //------------------------------------------------------------------------
 
-//%% struct MemberListInfo: member list information
-//%% {
 class MemberListInfoContext::Private
 {
   public:
-    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),
-      m_title(title),
-      m_subtitle(subtitle)
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("members",      &Private::members);
-        s_inst.addProperty("title",        &Private::title);
-        s_inst.addProperty("subtitle",     &Private::subtitle);
-        s_inst.addProperty("anchor",       &Private::anchor);
-        s_inst.addProperty("memberGroups", &Private::memberGroups);
-        s_inst.addProperty("inherited",    &Private::inherited);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant members() const
-    {
-      if (!m_cache.memberListContext)
-      {
-        m_cache.memberListContext.reset(MemberListContext::alloc(m_memberList));
-      }
-      return m_cache.memberListContext.get();
-    }
-    TemplateVariant title() const
-    {
-      return m_title;
-    }
-    TemplateVariant subtitle() const
-    {
-      return m_subtitle;
-    }
-    TemplateVariant anchor() const
+    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), m_title(title), m_subtitle(subtitle) {}
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant members() const              { return m_memberListCtx.get(this); }
+    TemplateVariant title() const                { return m_title; }
+    TemplateVariant subtitle() const             { return m_subtitle; }
+    TemplateVariant anchor() const               { return MemberList::listTypeAsString(m_memberList->listType()); }
+    TemplateVariant memberGroups() const         { return m_memberGroups.get(this); }
+    TemplateVariant inherited() const            { return m_inherited.get(this); }
+
+  private:
+
+    TemplateVariant createMemberList() const
     {
-      return MemberList::listTypeAsString(m_memberList->listType());
+      return MemberListContext::alloc(m_memberList);
     }
-    TemplateVariant memberGroups() const
+    TemplateVariant createMemberGroups() const
     {
-      if (!m_cache.memberGroups)
-      {
-        m_cache.memberGroups.reset(MemberGroupListContext::alloc(m_def,m_relPath,m_memberList->getMemberGroupList()));
-      }
-      return m_cache.memberGroups.get();
+      return MemberGroupListContext::alloc(m_def,m_relPath,m_memberList->getMemberGroupList());
     }
-    TemplateVariant inherited() const
+    TemplateVariant createInherited() const
     {
-      if (!m_cache.inherited && (m_memberList->listType()&MemberListType_detailedLists)==0 &&
+      if ((m_memberList->listType()&MemberListType_detailedLists)==0 &&
           m_def->definitionType()==Definition::TypeClass)
       {
-        InheritedMemberInfoListContext *ctx = InheritedMemberInfoListContext::alloc();
+        TemplateListIntfPtr list = InheritedMemberInfoListContext::alloc();
+        auto ctx = std::dynamic_pointer_cast<InheritedMemberInfoListContext>(list);
         ctx->addMemberList(toClassDef(m_def),m_memberList->listType(),m_title,FALSE);
-        m_cache.inherited.reset(ctx);
-      }
-      if (m_cache.inherited)
-      {
-        return m_cache.inherited.get();
+        return list;
       }
       else
       {
-        return TemplateVariant(FALSE);
+        return TemplateVariant(false);
       }
     }
-  private:
     const Definition *m_def;
     const MemberList *m_memberList;
     QCString m_relPath;
     QCString m_title;
     QCString m_subtitle;
-    struct Cachable
-    {
-      SharedPtr<MemberListContext> memberListContext;
-      SharedPtr<MemberGroupListContext> memberGroups;
-      SharedPtr<InheritedMemberInfoListContext> inherited;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<MemberListInfoContext::Private> s_inst;
+    CachedItem<TemplateVariant,  Private, &Private::createMemberList>    m_memberListCtx;
+    CachedItem<TemplateVariant,  Private, &Private::createMemberGroups>  m_memberGroups;
+    CachedItem<TemplateVariant,  Private, &Private::createInherited>     m_inherited;
+    static const PropertyMap<MemberListInfoContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<MemberListInfoContext::Private> MemberListInfoContext::Private::s_inst;
+//%% struct MemberListInfo: member list information
+//%% {
+const PropertyMap<MemberListInfoContext::Private> MemberListInfoContext::Private::s_inst {
+  {  "members",      &Private::members },
+  {  "title",        &Private::title },
+  {  "subtitle",     &Private::subtitle },
+  {  "anchor",       &Private::anchor },
+  {  "memberGroups", &Private::memberGroups },
+  {  "inherited",    &Private::inherited }
+};
+//%% }
 
 MemberListInfoContext::MemberListInfoContext(
            const Definition *def,const QCString &relPath,const MemberList *ml,
-           const QCString &title,const QCString &subtitle) : RefCountedContext("MemberListInfoContext")
+           const QCString &title,const QCString &subtitle) : p(std::make_unique<Private>(def,relPath,ml,title,subtitle))
 {
-  p = new Private(def,relPath,ml,title,subtitle);
 }
 
 MemberListInfoContext::~MemberListInfoContext()
 {
-  delete p;
 }
 
 TemplateVariant MemberListInfoContext::get(const QCString &name) const
@@ -9800,95 +7988,69 @@ StringVector MemberListInfoContext::fields() const
 
 //------------------------------------------------------------------------
 
-//%% struct InheritedMemberInfo: inherited member information
-//%% {
 class InheritedMemberInfoContext::Private
 {
   public:
-    Private(const ClassDef *cd,const MemberList *ml,const QCString &title)
-      : m_class(cd), m_memberList(ml), m_title(title)
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("class",         &Private::getClass);
-        s_inst.addProperty("title",         &Private::title);
-        s_inst.addProperty("members",       &Private::members);
-        s_inst.addProperty("id",            &Private::id);
-        s_inst.addProperty("inheritedFrom", &Private::inheritedFrom);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    virtual ~Private()
-    {
-      delete m_memberList;
-    }
-    TemplateVariant getClass() const
-    {
-      if (!m_classCtx)
-      {
-        m_classCtx.reset(ClassContext::alloc(m_class));
-      }
-      return m_classCtx.get();
-    }
-    TemplateVariant title() const
+    Private(const ClassDef *cd,std::unique_ptr<MemberList> &&ml,const QCString &title)
+      : m_class(cd), m_memberList(std::move(ml)), m_title(title) {}
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant getClass() const             { return m_classCtx.get(this); }
+    TemplateVariant title() const                { return m_title; }
+    TemplateVariant members() const              { return m_memberListCtx.get(this); }
+    TemplateVariant inheritedFrom() const        { return m_inheritedFrom.get(this); }
+    TemplateVariant id() const
     {
-      return m_title;
+      return substitute(MemberList::listTypeAsString(m_memberList->listType()),"-","_")+"_"+
+                        stripPath(m_class->getOutputFileBase());
     }
-    TemplateVariant members() const
+
+  private:
+    TemplateVariant createClass() const
     {
-      if (!m_memberListCtx)
-      {
-        m_memberListCtx.reset(MemberListContext::alloc(m_memberList));
-      }
-      return m_memberListCtx.get();
+      return ClassContext::alloc(m_class);
     }
-    TemplateVariant id() const
+    TemplateVariant createMemberList() const
     {
-      return substitute(MemberList::listTypeAsString(m_memberList->listType()),"-","_")+"_"+
-                        stripPath(m_class->getOutputFileBase());
+      return MemberListContext::alloc(m_memberList.get());
     }
-    TemplateVariant inheritedFrom() const
+    TemplateVariant createInheritedFrom() const
     {
-      if (!m_inheritedFrom)
-      {
-        m_inheritedFrom.reset(TemplateList::alloc());
-        m_inheritedFrom->append(title());
-        m_inheritedFrom->append(getClass());
-      }
-      return m_inheritedFrom.get();
+      return TemplateImmutableList::alloc({ TemplateVariant(title()), TemplateVariant(getClass()) });
     }
 
-  private:
     const ClassDef *  m_class;
-    const MemberList *m_memberList;
+    std::unique_ptr<const MemberList> m_memberList;
     QCString    m_title;
-    mutable SharedPtr<ClassContext> m_classCtx;
-    mutable SharedPtr<MemberListContext> m_memberListCtx;
-    mutable SharedPtr<TemplateList> m_inheritedFrom;
-    static PropertyMapper<InheritedMemberInfoContext::Private> s_inst;
+    CachedItem<TemplateVariant, Private, &Private::createClass>         m_classCtx;
+    CachedItem<TemplateVariant, Private, &Private::createMemberList>    m_memberListCtx;
+    CachedItem<TemplateVariant, Private, &Private::createInheritedFrom> m_inheritedFrom;
+    static const PropertyMap<InheritedMemberInfoContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<InheritedMemberInfoContext::Private> InheritedMemberInfoContext::Private::s_inst;
+//%% struct InheritedMemberInfo: inherited member information
+//%% {
+const PropertyMap<InheritedMemberInfoContext::Private> InheritedMemberInfoContext::Private::s_inst {
+  {  "class",         &Private::getClass },
+  {  "title",         &Private::title },
+  {  "members",       &Private::members },
+  {  "id",            &Private::id },
+  {  "inheritedFrom", &Private::inheritedFrom }
+};
+//%% }
 
-InheritedMemberInfoContext::InheritedMemberInfoContext(const ClassDef *cd,const MemberList *ml,
-                                                       const QCString &title) : RefCountedContext("InheritedMemberInfoContext")
+InheritedMemberInfoContext::InheritedMemberInfoContext(const ClassDef *cd,std::unique_ptr<MemberList> &&ml,const QCString &title)
+  : p(std::make_unique<Private>(cd,std::move(ml),title))
 {
-  p = new Private(cd,ml,title);
 }
 
 InheritedMemberInfoContext::~InheritedMemberInfoContext()
 {
-  delete p;
 }
 
 TemplateVariant InheritedMemberInfoContext::get(const QCString &name) const
@@ -9958,12 +8120,12 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext
       {
         const MemberList *ml  = cd->getMemberList(lt1);
         const MemberList *ml2 = lt2!=-1 ? cd->getMemberList((MemberListType)lt2) : 0;
-        MemberList *combinedList = new MemberList(lt,MemberListContainer::Class);
-        addMemberListIncludingGrouped(inheritedFrom,ml,combinedList);
-        addMemberListIncludingGrouped(inheritedFrom,ml2,combinedList);
-        addMemberGroupsOfClass(inheritedFrom,cd,lt,combinedList);
-        if (lt2!=-1) addMemberGroupsOfClass(inheritedFrom,cd,(MemberListType)lt2,combinedList);
-        append(InheritedMemberInfoContext::alloc(cd,combinedList,title));
+        std::unique_ptr<MemberList> combinedList = std::make_unique<MemberList>(lt,MemberListContainer::Class);
+        addMemberListIncludingGrouped(inheritedFrom,ml,combinedList.get());
+        addMemberListIncludingGrouped(inheritedFrom,ml2,combinedList.get());
+        addMemberGroupsOfClass(inheritedFrom,cd,lt,combinedList.get());
+        if (lt2!=-1) addMemberGroupsOfClass(inheritedFrom,cd,(MemberListType)lt2,combinedList.get());
+        append(InheritedMemberInfoContext::alloc(cd,std::move(combinedList),title));
       }
     }
     void findInheritedMembers(const ClassDef *inheritedFrom,const ClassDef *cd,MemberListType lt,
@@ -9997,9 +8159,8 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext
     }
 };
 
-InheritedMemberInfoListContext::InheritedMemberInfoListContext() : RefCountedContext("InheritedMemberInfoListContext")
+InheritedMemberInfoListContext::InheritedMemberInfoListContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 void InheritedMemberInfoListContext::addMemberList(
@@ -10018,7 +8179,6 @@ void InheritedMemberInfoListContext::addMemberList(
 
 InheritedMemberInfoListContext::~InheritedMemberInfoListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -10032,79 +8192,31 @@ TemplateVariant InheritedMemberInfoListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *InheritedMemberInfoListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr InheritedMemberInfoListContext::createIterator() const
 {
   return p->createIterator();
 }
 
 //------------------------------------------------------------------------
 
-//%% struct Argument: parameter information
-//%% {
 class ArgumentContext::Private
 {
   public:
-    Private(const Argument &arg,const Definition *def,const QCString &relPath) :
-      m_argument(arg), m_def(def), m_relPath(relPath)
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("type",     &Private::type);
-        s_inst.addProperty("name",     &Private::name);
-        s_inst.addProperty("defVal",   &Private::defVal);
-        s_inst.addProperty("docs",     &Private::docs);
-        s_inst.addProperty("attrib",   &Private::attrib);
-        s_inst.addProperty("array",    &Private::array);
-        s_inst.addProperty("namePart", &Private::namePart);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant type() const
-    {
-      return createLinkedText(m_def,m_relPath,m_argument.type);
-    }
-    TemplateVariant attrib() const
-    {
-      return m_argument.attrib;
-    }
-    TemplateVariant name() const
-    {
-      return m_argument.name;
-    }
-    TemplateVariant defVal() const
-    {
-      return createLinkedText(m_def,m_relPath,m_argument.defval);
-    }
-    TemplateVariant array() const
-    {
-      return m_argument.array;
-    }
-    TemplateVariant docs() const
-    {
-      if (!m_cache.docs && m_def)
-      {
-        if (!m_argument.docs.isEmpty())
-        {
-          m_cache.docs.reset(new TemplateVariant(
-                             parseDoc(m_def,m_def->docFile(),m_def->docLine(),
-                             m_relPath,m_argument.docs,TRUE)));
-        }
-        else
-        {
-          m_cache.docs.reset(new TemplateVariant(""));
-        }
-      }
-      return *m_cache.docs;
-    }
+    Private(const Argument &arg,const Definition *def,const QCString &relPath)
+      : m_argument(arg), m_def(def), m_relPath(relPath) {}
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant type() const                 { return m_type.get(this); }
+    TemplateVariant attrib() const               { return m_argument.attrib; }
+    TemplateVariant name() const                 { return m_argument.name; }
+    TemplateVariant defVal() const               { return m_defval.get(this); }
+    TemplateVariant array() const                { return m_argument.array; }
+    TemplateVariant docs() const                 { return m_docs.get(this); }
     TemplateVariant namePart() const
     {
       QCString result = m_argument.attrib;
@@ -10116,29 +8228,51 @@ class ArgumentContext::Private
       }
       return result;
     }
+
   private:
+    TemplateVariant createType() const
+    {
+      return createLinkedText(m_def,m_relPath,m_argument.type);
+    }
+    TemplateVariant createDefval() const
+    {
+      return createLinkedText(m_def,m_relPath,m_argument.defval);
+    }
+    TemplateVariant createDocs() const
+    {
+      return !m_argument.docs.isEmpty() ?
+          TemplateVariant(parseDoc(m_def,m_def->docFile(),m_def->docLine(),m_relPath,m_argument.docs,TRUE)) :
+          TemplateVariant("");
+    }
     Argument m_argument;
     const Definition *m_def;
     QCString m_relPath;
-    struct Cachable
-    {
-      std::unique_ptr<TemplateVariant> docs;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<ArgumentContext::Private> s_inst;
+    CachedItem<TemplateVariant, Private, &Private::createType>   m_type;
+    CachedItem<TemplateVariant, Private, &Private::createDefval> m_defval;
+    CachedItem<TemplateVariant, Private, &Private::createDocs>   m_docs;
+    static const PropertyMap<ArgumentContext::Private> s_inst;
+};
+
+//%% struct Argument: parameter information
+//%% {
+const PropertyMap<ArgumentContext::Private> ArgumentContext::Private::s_inst {
+  {  "type",     &Private::type },
+  {  "name",     &Private::name },
+  {  "defVal",   &Private::defVal },
+  {  "docs",     &Private::docs },
+  {  "attrib",   &Private::attrib },
+  {  "array",    &Private::array },
+  {  "namePart", &Private::namePart }
 };
 //%% }
 
-PropertyMapper<ArgumentContext::Private> ArgumentContext::Private::s_inst;
 
-ArgumentContext::ArgumentContext(const Argument &al,const Definition *def,const QCString &relPath) : RefCountedContext("ArgumentContext")
+ArgumentContext::ArgumentContext(const Argument &al,const Definition *def,const QCString &relPath) : p(std::make_unique<Private>(al,def,relPath))
 {
-  p = new Private(al,def,relPath);
 }
 
 ArgumentContext::~ArgumentContext()
 {
-  delete p;
 }
 
 TemplateVariant ArgumentContext::get(const QCString &name) const
@@ -10163,15 +8297,13 @@ class ArgumentListContext::Private : public GenericNodeListContext
     }
 };
 
-ArgumentListContext::ArgumentListContext() : RefCountedContext("ArgumentListContext")
+ArgumentListContext::ArgumentListContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 ArgumentListContext::ArgumentListContext(const ArgumentList &list,
-                        const Definition *def,const QCString &relPath) : RefCountedContext("ArgumentListContext")
+                        const Definition *def,const QCString &relPath) : p(std::make_unique<Private>())
 {
-  p = new Private;
   for (const Argument &arg : list)
   {
     p->addArgument(arg,def,relPath);
@@ -10180,7 +8312,6 @@ ArgumentListContext::ArgumentListContext(const ArgumentList &list,
 
 ArgumentListContext::~ArgumentListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -10194,7 +8325,7 @@ TemplateVariant ArgumentListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *ArgumentListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr ArgumentListContext::createIterator() const
 {
   return p->createIterator();
 }
@@ -10218,41 +8349,25 @@ TemplateListIntf::ConstIterator *ArgumentListContext::createIterator() const
 
 //------------------------------------------------------------------------
 
-//%% struct SymbolGroup: search group of similar symbols
-//%% {
 class SymbolContext::Private
 {
   public:
-    Private(const Definition *d,const Definition *prev,
-            const Definition *next) : m_def(d), m_prevDef(prev), m_nextDef(next)
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("fileName",&Private::fileName);
-        s_inst.addProperty("anchor",  &Private::anchor);
-        s_inst.addProperty("scope",   &Private::scope);
-        s_inst.addProperty("relPath", &Private::relPath);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant fileName() const
-    {
-      return m_def->getOutputFileBase();
-    }
-    TemplateVariant anchor() const
-    {
-      return m_def->anchor();
-    }
-    TemplateVariant scope() const
+    Private(const Definition *d,const Definition *prev, const Definition *next)
+      : m_def(d), m_prevDef(prev), m_nextDef(next) {}
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant fileName() const             { return m_def->getOutputFileBase(); }
+    TemplateVariant anchor() const               { return m_def->anchor(); }
+    TemplateVariant scope() const                { return m_scope.get(this); }
+    TemplateVariant relPath() const              { return externalRef("../",m_def->getReference(),TRUE); }
+
+  private:
+    TemplateVariant createScope() const
     {
       const Definition *scope     = m_def->getOuterScope();
       const Definition *next      = m_nextDef;
@@ -10283,7 +8398,6 @@ class SymbolContext::Private
       }
       else
       {
-
         QCString prefix;
         if (md) prefix=md->localName();
         if (overloadedFunction) // overloaded member function
@@ -10340,29 +8454,29 @@ class SymbolContext::Private
       }
       return name;
     }
-    TemplateVariant relPath() const
-    {
-      return externalRef("../",m_def->getReference(),TRUE);
-    }
-  private:
     const Definition *m_def;
     const Definition *m_prevDef;
     const Definition *m_nextDef;
-    static PropertyMapper<SymbolContext::Private> s_inst;
+    CachedItem<TemplateVariant,Private,&Private::createScope> m_scope;
+    static const PropertyMap<SymbolContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<SymbolContext::Private> SymbolContext::Private::s_inst;
+//%% struct Symbol: specific search item
+//%% {
+const PropertyMap<SymbolContext::Private> SymbolContext::Private::s_inst {
+  {  "fileName",&Private::fileName },
+  {  "anchor",  &Private::anchor },
+  {  "scope",   &Private::scope },
+  {  "relPath", &Private::relPath }
+};
+//%% }
 
-SymbolContext::SymbolContext(const Definition *def,const Definition *prevDef,const Definition *nextDef)
-    : RefCountedContext("SymbolContext")
+SymbolContext::SymbolContext(const Definition *def,const Definition *prevDef,const Definition *nextDef) : p(std::make_unique<Private>(def,prevDef,nextDef))
 {
-  p = new Private(def,prevDef,nextDef);
 }
 
 SymbolContext::~SymbolContext()
 {
-  delete p;
 }
 
 TemplateVariant SymbolContext::get(const QCString &name) const
@@ -10397,15 +8511,12 @@ class SymbolListContext::Private : public GenericNodeListContext
 };
 
 SymbolListContext::SymbolListContext(const SearchIndexList::const_iterator &start,
-                                     const SearchIndexList::const_iterator &end)
-    : RefCountedContext("SymbolListContext")
+                                     const SearchIndexList::const_iterator &end) : p(std::make_unique<Private>(start,end))
 {
-  p = new Private(start,end);
 }
 
 SymbolListContext::~SymbolListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -10419,78 +8530,58 @@ TemplateVariant SymbolListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *SymbolListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr SymbolListContext::createIterator() const
 {
   return p->createIterator();
 }
 
 //------------------------------------------------------------------------
 
-//%% struct SymbolGroup: search group of similar symbols
-//%% {
 class SymbolGroupContext::Private
 {
   public:
-    Private(const SearchIndexList::const_iterator &start,
-            const SearchIndexList::const_iterator &end) : m_start(start), m_end(end)
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("id",     &Private::id);
-        s_inst.addProperty("name",   &Private::name);
-        s_inst.addProperty("symbols",&Private::symbolList);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant id() const
-    {
-      return searchId(*m_start);
-    }
-    TemplateVariant name() const
-    {
-      return searchName(*m_start);
-    }
-    TemplateVariant symbolList() const
+    Private(const SearchIndexList::const_iterator &start, const SearchIndexList::const_iterator &end)
+      : m_start(start), m_end(end) {}
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant id() const                   { return searchId(*m_start); }
+    TemplateVariant name() const                 { return searchName(*m_start); }
+    TemplateVariant symbolList() const           { return m_symbolList.get(this); }
+
+  private:
+
+    TemplateVariant createSymbolList() const
     {
-      if (!m_cache.symbolList)
-      {
-        m_cache.symbolList.reset(SymbolListContext::alloc(m_start,m_end));
-      }
-      return m_cache.symbolList.get();
+      return SymbolListContext::alloc(m_start,m_end);
     }
-  private:
+
     SearchIndexList::const_iterator m_start;
     SearchIndexList::const_iterator m_end;
-    struct Cachable
-    {
-      SharedPtr<SymbolListContext> symbolList;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<SymbolGroupContext::Private> s_inst;
+    CachedItem<TemplateVariant,Private,&Private::createSymbolList> m_symbolList;
+    static const PropertyMap<SymbolGroupContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<SymbolGroupContext::Private> SymbolGroupContext::Private::s_inst;
+//%% struct SymbolGroup: search group of similar symbols
+//%% {
+const PropertyMap<SymbolGroupContext::Private> SymbolGroupContext::Private::s_inst {
+  {  "id",     &Private::id },
+  {  "name",   &Private::name },
+  {  "symbols",&Private::symbolList }
+};
+//%% }
 
 SymbolGroupContext::SymbolGroupContext(const SearchIndexList::const_iterator &start,
-                                       const SearchIndexList::const_iterator &end)
-    : RefCountedContext("SymbolGroupContext")
+                                       const SearchIndexList::const_iterator &end) : p(std::make_unique<Private>(start,end))
 {
-  p = new Private(start,end);
 }
 
 SymbolGroupContext::~SymbolGroupContext()
 {
-  delete p;
 }
 
 TemplateVariant SymbolGroupContext::get(const QCString &name) const
@@ -10535,15 +8626,12 @@ class SymbolGroupListContext::Private : public GenericNodeListContext
     }
 };
 
-SymbolGroupListContext::SymbolGroupListContext(const SearchIndexList &sil)
-    : RefCountedContext("SymbolGroupListContext")
+SymbolGroupListContext::SymbolGroupListContext(const SearchIndexList &sil) : p(std::make_unique<Private>(sil))
 {
-  p = new Private(sil);
 }
 
 SymbolGroupListContext::~SymbolGroupListContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -10557,79 +8645,56 @@ TemplateVariant SymbolGroupListContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *SymbolGroupListContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr SymbolGroupListContext::createIterator() const
 {
   return p->createIterator();
 }
 
 //------------------------------------------------------------------------
 
-//%% struct SymbolIndex: search index
-//%% {
 class SymbolIndexContext::Private
 {
   public:
-    Private(const std::string &letter,
-            const SearchIndexList &sl,
-            const QCString &name) : m_letter(letter), m_searchList(sl), m_name(name)
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("name",        &Private::name);
-        s_inst.addProperty("letter",      &Private::letter);
-        s_inst.addProperty("symbolGroups",&Private::symbolGroups);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant name() const
-    {
-      return m_name;
-    }
-    TemplateVariant letter() const
-    {
-      return m_letter;
-    }
-    TemplateVariant symbolGroups() const
+    Private(const std::string &letter, const SearchIndexList &sl, const QCString &name)
+      : m_letter(letter), m_searchList(sl), m_name(name) {}
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant name() const                 { return m_name; }
+    TemplateVariant letter() const               { return m_letter; }
+    TemplateVariant symbolGroups() const         { return m_symbolGroups.get(this); }
+
+  private:
+
+    TemplateVariant createSymbolGroups() const
     {
-      if (!m_cache.symbolGroups)
-      {
-        m_cache.symbolGroups.reset(SymbolGroupListContext::alloc(m_searchList));
-      }
-      return m_cache.symbolGroups.get();
+      return SymbolGroupListContext::alloc(m_searchList);
     }
-  private:
     QCString m_letter;
     const SearchIndexList &m_searchList;
     QCString m_name;
-    struct Cachable
-    {
-      SharedPtr<SymbolGroupListContext> symbolGroups;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<SymbolIndexContext::Private> s_inst;
+    CachedItem<TemplateVariant,Private,&Private::createSymbolGroups> m_symbolGroups;
+    static const PropertyMap<SymbolIndexContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<SymbolIndexContext::Private> SymbolIndexContext::Private::s_inst;
+//%% struct SymbolIndex: search index
+//%% {
+const PropertyMap<SymbolIndexContext::Private> SymbolIndexContext::Private::s_inst {
+  {  "name",        &Private::name },
+  {  "letter",      &Private::letter },
+  {  "symbolGroups",&Private::symbolGroups },
+};
+//%% }
 
-SymbolIndexContext::SymbolIndexContext(const std::string &letter,const SearchIndexList &sl,const QCString &name)
-    : RefCountedContext("SymbolIndexContext")
+SymbolIndexContext::SymbolIndexContext(const std::string &letter,const SearchIndexList &sl,const QCString &name) : p(std::make_unique<Private>(letter,sl,name))
 {
-  p = new Private(letter,sl,name);
 }
 
 SymbolIndexContext::~SymbolIndexContext()
 {
-  delete p;
 }
 
 TemplateVariant SymbolIndexContext::get(const QCString &name) const
@@ -10658,14 +8723,12 @@ class SymbolIndicesContext::Private : public GenericNodeListContext
     }
 };
 
-SymbolIndicesContext::SymbolIndicesContext(const SearchIndexInfo &info) : RefCountedContext("SymbolIndicesContext")
+SymbolIndicesContext::SymbolIndicesContext(const SearchIndexInfo &info) : p(std::make_unique<Private>(info))
 {
-  p = new Private(info);
 }
 
 SymbolIndicesContext::~SymbolIndicesContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -10679,75 +8742,54 @@ TemplateVariant SymbolIndicesContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *SymbolIndicesContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr SymbolIndicesContext::createIterator() const
 {
   return p->createIterator();
 }
 
 //------------------------------------------------------------------------
 
-//%% struct SearchIndex: search index
-//%% {
 class SearchIndexContext::Private
 {
   public:
-    Private(const SearchIndexInfo &info) : m_info(info)
-    {
-      static bool init=FALSE;
-      if (!init)
-      {
-        s_inst.addProperty("name",         &Private::name);
-        s_inst.addProperty("text",         &Private::text);
-        s_inst.addProperty("symbolIndices",&Private::symbolIndices);
-        init=TRUE;
-      }
-    }
-    TemplateVariant get(const QCString &n) const
-    {
-      return s_inst.get(this,n);
-    }
-    StringVector fields() const
-    {
-      return s_inst.fields();
-    }
-    TemplateVariant name() const
-    {
-      return m_info.name;
-    }
-    TemplateVariant text() const
-    {
-      return m_info.getText();
-    }
-    TemplateVariant symbolIndices() const
+    Private(const SearchIndexInfo &info) : m_info(info) {}
+
+    // TemplateStructIntf methods
+    TemplateVariant get(const QCString &n) const { return s_inst.get(this,n); }
+    StringVector fields() const                  { return s_inst.fields(); }
+
+  private:
+    // Property getters
+    TemplateVariant name() const                 { return m_info.name; }
+    TemplateVariant text() const                 { return m_info.getText(); }
+    TemplateVariant symbolIndices() const        { return m_symbolIndices.get(this); }
+
+  private:
+    TemplateVariant createSymbolIndices() const
     {
-      if (!m_cache.symbolIndices)
-      {
-        m_cache.symbolIndices.reset(SymbolIndicesContext::alloc(m_info));
-      }
-      return m_cache.symbolIndices.get();
+      return SymbolIndicesContext::alloc(m_info);
     }
-  private:
+
     const SearchIndexInfo &m_info;
-    struct Cachable
-    {
-      SharedPtr<SymbolIndicesContext> symbolIndices;
-    };
-    mutable Cachable m_cache;
-    static PropertyMapper<SearchIndexContext::Private> s_inst;
+    CachedItem<TemplateVariant, Private, &Private::createSymbolIndices> m_symbolIndices;
+    static const PropertyMap<SearchIndexContext::Private> s_inst;
 };
-//%% }
 
-PropertyMapper<SearchIndexContext::Private> SearchIndexContext::Private::s_inst;
+//%% struct SearchIndex: search index
+//%% {
+const PropertyMap<SearchIndexContext::Private> SearchIndexContext::Private::s_inst {
+  {  "name",         &Private::name },
+  {  "text",         &Private::text },
+  {  "symbolIndices",&Private::symbolIndices }
+};
+//%% }
 
-SearchIndexContext::SearchIndexContext(const SearchIndexInfo &info)
-    : RefCountedContext("SearchIndexContext")
+SearchIndexContext::SearchIndexContext(const SearchIndexInfo &info) : p(std::make_unique<Private>(info))
 {
-  p = new Private(info);
 }
 
 SearchIndexContext::~SearchIndexContext()
 {
-  delete p;
 }
 
 TemplateVariant SearchIndexContext::get(const QCString &name) const
@@ -10776,14 +8818,12 @@ class SearchIndicesContext::Private : public GenericNodeListContext
     }
 };
 
-SearchIndicesContext::SearchIndicesContext() : RefCountedContext("SearchIndicesContext")
+SearchIndicesContext::SearchIndicesContext() : p(std::make_unique<Private>())
 {
-  p = new Private;
 }
 
 SearchIndicesContext::~SearchIndicesContext()
 {
-  delete p;
 }
 
 // TemplateListIntf
@@ -10797,7 +8837,7 @@ TemplateVariant SearchIndicesContext::at(uint index) const
   return p->at(index);
 }
 
-TemplateListIntf::ConstIterator *SearchIndicesContext::createIterator() const
+TemplateListIntf::ConstIteratorPtr SearchIndicesContext::createIterator() const
 {
   return p->createIterator();
 }
@@ -10808,6 +8848,10 @@ TemplateListIntf::ConstIterator *SearchIndicesContext::createIterator() const
 class HtmlEscaper : public TemplateEscapeIntf
 {
   public:
+    std::unique_ptr<TemplateEscapeIntf> clone()
+    {
+      return std::make_unique<HtmlEscaper>(*this);
+    }
     QCString escape(const QCString &s)
     {
       return convertToHtml(s,TRUE);
@@ -10821,6 +8865,10 @@ class LatexSpaceless : public TemplateSpacelessIntf
 {
   public:
     LatexSpaceless() { reset(); }
+    std::unique_ptr<TemplateSpacelessIntf> clone()
+    {
+      return std::make_unique<LatexSpaceless>(*this);
+    }
     void reset() { }
     QCString remove(const QCString &s)
     {
@@ -10850,6 +8898,10 @@ class HtmlSpaceless : public TemplateSpacelessIntf
 {
   public:
     HtmlSpaceless() { reset(); }
+    std::unique_ptr<TemplateSpacelessIntf> clone()
+    {
+      return std::make_unique<HtmlSpaceless>(*this);
+    }
     void reset()
     {
       m_insideTag = FALSE;
@@ -10924,6 +8976,10 @@ class HtmlSpaceless : public TemplateSpacelessIntf
 class LatexEscaper : public TemplateEscapeIntf
 {
   public:
+    std::unique_ptr<TemplateEscapeIntf> clone()
+    {
+      return std::make_unique<LatexEscaper>(*this);
+    }
     LatexEscaper() : m_tabbing(FALSE) {}
     QCString escape(const QCString &s)
     {
@@ -10937,112 +8993,107 @@ class LatexEscaper : public TemplateEscapeIntf
 
 //------------------------------------------------------------------------
 
-#if DEBUG_REF
-int RefCountedContext::s_totalCount;
-#endif
-
 void generateOutputViaTemplate()
 {
-  msg("Generating output via template engine...\n");
   {
-    TemplateEngine e;
-    TemplateContext *ctx = e.createContext();
+    auto e = std::make_unique<TemplateEngine>();
+    auto ctx = e->createContext();
     if (ctx)
     {
-      SharedPtr<DoxygenContext>               doxygen              (DoxygenContext::alloc());
-      SharedPtr<ConfigContext>                config               (ConfigContext::alloc());
-      SharedPtr<TranslateContext>             tr                   (TranslateContext::alloc());
-      SharedPtr<ClassListContext>             classList            (ClassListContext::alloc());
-      SharedPtr<ClassIndexContext>            classIndex           (ClassIndexContext::alloc());
-      SharedPtr<ClassTreeContext>             classTree            (ClassTreeContext::alloc());
-      SharedPtr<ClassHierarchyContext>        classHierarchy       (ClassHierarchyContext::alloc());
-      SharedPtr<ConceptListContext>           conceptList          (ConceptListContext::alloc());
-      SharedPtr<ConceptTreeContext>           conceptTree          (ConceptTreeContext::alloc());
-      SharedPtr<NamespaceListContext>         namespaceList        (NamespaceListContext::alloc());
-      SharedPtr<NamespaceTreeContext>         namespaceTree        (NamespaceTreeContext::alloc());
-      SharedPtr<DirListContext>               dirList              (DirListContext::alloc());
-      SharedPtr<FileListContext>              fileList             (FileListContext::alloc());
-      SharedPtr<FileTreeContext>              fileTree             (FileTreeContext::alloc());
-      SharedPtr<PageTreeContext>              pageTree             (PageTreeContext::alloc(*Doxygen::pageLinkedMap));
-      SharedPtr<PageListContext>              pageList             (PageListContext::alloc(*Doxygen::pageLinkedMap));
-      SharedPtr<ExampleTreeContext>           exampleTree          (ExampleTreeContext::alloc());
-      SharedPtr<ExampleListContext>           exampleList          (ExampleListContext::alloc());
-      SharedPtr<ModuleTreeContext>            moduleTree           (ModuleTreeContext::alloc());
-      SharedPtr<ModuleListContext>            moduleList           (ModuleListContext::alloc());
-      SharedPtr<GlobalsIndexContext>          globalsIndex         (GlobalsIndexContext::alloc());
-      SharedPtr<ClassMembersIndexContext>     classMembersIndex    (ClassMembersIndexContext::alloc());
-      SharedPtr<NamespaceMembersIndexContext> namespaceMembersIndex(NamespaceMembersIndexContext::alloc());
-      SharedPtr<SearchIndicesContext>         searchIndices        (SearchIndicesContext::alloc());
+      TemplateStructIntfPtr doxygen              (DoxygenContext::alloc());
+      TemplateStructIntfPtr config               (ConfigContext::alloc());
+      TemplateStructIntfPtr tr                   (TranslateContext::alloc());
+      TemplateListIntfPtr   classList            (ClassListContext::alloc());
+      TemplateStructIntfPtr classIndex           (ClassIndexContext::alloc());
+      TemplateStructIntfPtr classTree            (ClassTreeContext::alloc());
+      TemplateStructIntfPtr classHierarchy       (ClassHierarchyContext::alloc());
+      TemplateListIntfPtr   conceptList          (ConceptListContext::alloc());
+      TemplateStructIntfPtr conceptTree          (ConceptTreeContext::alloc());
+      TemplateListIntfPtr   namespaceList        (NamespaceListContext::alloc());
+      TemplateStructIntfPtr namespaceTree        (NamespaceTreeContext::alloc());
+      TemplateListIntfPtr   dirList              (DirListContext::alloc());
+      TemplateListIntfPtr   fileList             (FileListContext::alloc());
+      TemplateStructIntfPtr fileTree             (FileTreeContext::alloc());
+      TemplateStructIntfPtr pageTree             (PageTreeContext::alloc(*Doxygen::pageLinkedMap));
+      TemplateListIntfPtr   pageList             (PageListContext::alloc(*Doxygen::pageLinkedMap));
+      TemplateStructIntfPtr exampleTree          (ExampleTreeContext::alloc());
+      TemplateListIntfPtr   exampleList          (ExampleListContext::alloc());
+      TemplateStructIntfPtr moduleTree           (ModuleTreeContext::alloc());
+      TemplateListIntfPtr   moduleList           (ModuleListContext::alloc());
+      TemplateStructIntfPtr globalsIndex         (GlobalsIndexContext::alloc());
+      TemplateStructIntfPtr classMembersIndex    (ClassMembersIndexContext::alloc());
+      TemplateStructIntfPtr namespaceMembersIndex(NamespaceMembersIndexContext::alloc());
+      TemplateListIntfPtr   searchIndices        (SearchIndicesContext::alloc());
 
       //%% Doxygen doxygen:
-      ctx->set("doxygen",doxygen.get());
+      ctx->set("doxygen",doxygen);
       //%% Translator tr:
-      ctx->set("tr",tr.get());
+      ctx->set("tr",tr);
       //%% Config config:
-      ctx->set("config",config.get());
+      ctx->set("config",config);
       //%% ClassList classList:
-      ctx->set("classList",classList.get()); // not used for standard HTML
+      ctx->set("classList",classList); // not used for standard HTML
       //%% ClassTree classTree:
-      ctx->set("classTree",classTree.get());
+      ctx->set("classTree",classTree);
       //%% ClassIndex classIndex:
-      ctx->set("classIndex",classIndex.get());
+      ctx->set("classIndex",classIndex);
       //%% ClassHierarchy classHierarchy:
-      ctx->set("classHierarchy",classHierarchy.get());
+      ctx->set("classHierarchy",classHierarchy);
       //%% ConceptList conceptList:
-      ctx->set("conceptList",conceptList.get());
+      ctx->set("conceptList",conceptList);
       //%% ConceptTree conceptTree:
-      ctx->set("conceptTree",conceptTree.get());
+      ctx->set("conceptTree",conceptTree);
       //%% NamespaceList namespaceList:
-      ctx->set("namespaceList",namespaceList.get());
+      ctx->set("namespaceList",namespaceList);
       //%% NamespaceTree namespaceTree:
-      ctx->set("namespaceTree",namespaceTree.get());
+      ctx->set("namespaceTree",namespaceTree);
       //%% FileList fileList:
-      ctx->set("fileList",fileList.get());
+      ctx->set("fileList",fileList);
       //%% FileTree fileTree:
-      ctx->set("fileTree",fileTree.get());
+      ctx->set("fileTree",fileTree);
       //%% PageList pageList
-      ctx->set("pageList",pageList.get());
+      ctx->set("pageList",pageList);
       //%% PageTree pageTree
-      ctx->set("pageTree",pageTree.get());
+      ctx->set("pageTree",pageTree);
       //%% ExampleTree exampleTree
-      ctx->set("exampleTree",exampleTree.get());
+      ctx->set("exampleTree",exampleTree);
       //%% ExampleList exampleList
-      ctx->set("exampleList",exampleList.get());
+      ctx->set("exampleList",exampleList);
       //%% ModuleTree moduleTree
-      ctx->set("moduleTree",moduleTree.get());
+      ctx->set("moduleTree",moduleTree);
       //%% ModuleList moduleList
-      ctx->set("moduleList",moduleList.get());
+      ctx->set("moduleList",moduleList);
       //%% DirList dirList
-      ctx->set("dirList",dirList.get());
+      ctx->set("dirList",dirList);
       //%% Page mainPage
       if (Doxygen::mainPage)
       {
-        SharedPtr<PageContext> mainPage(PageContext::alloc(Doxygen::mainPage.get(),TRUE,FALSE));
-        ctx->set("mainPage",mainPage.get());
+        TemplateStructIntfPtr mainPage = PageContext::alloc(Doxygen::mainPage.get(),TRUE,FALSE);
+        ctx->set("mainPage",mainPage);
       }
       else
       {
         // TODO: for LaTeX output index should be main... => solve in template
         Doxygen::mainPage.reset(createPageDef("[generated]",1,"index","",Config_getString(PROJECT_NAME)));
         Doxygen::mainPage->setFileName("index");
-        SharedPtr<PageContext> mainPage(PageContext::alloc(Doxygen::mainPage.get(),TRUE,FALSE));
-        ctx->set("mainPage",mainPage.get());
+        TemplateStructIntfPtr mainPage = PageContext::alloc(Doxygen::mainPage.get(),TRUE,FALSE);
+        ctx->set("mainPage",mainPage);
       }
       //%% GlobalsIndex globalsIndex:
-      ctx->set("globalsIndex",globalsIndex.get());
+      ctx->set("globalsIndex",globalsIndex);
       //%% ClassMembersIndex classMembersIndex:
-      ctx->set("classMembersIndex",classMembersIndex.get());
+      ctx->set("classMembersIndex",classMembersIndex);
       //%% NamespaceMembersIndex namespaceMembersIndex:
-      ctx->set("namespaceMembersIndex",namespaceMembersIndex.get());
+      ctx->set("namespaceMembersIndex",namespaceMembersIndex);
       //%% SearchIndices searchIndices
-      ctx->set("searchIndices",searchIndices.get());
+      ctx->set("searchIndices",searchIndices);
       //%% string space
       ctx->set("space"," ");
 
       //if (Config_getBool(GENERATE_HTML))
       { // render HTML output
-        e.setTemplateDir("templates/html"); // TODO: make template part user configurable
-        Template *tpl = e.loadByName("htmllayout.tpl",1);
+        e->setTemplateDir("templates/html"); // TODO: make template part user configurable
+        Template *tpl = e->loadByName("htmllayout.tpl",1);
         if (tpl)
         {
           g_globals.outputFormat = ContextOutputFormat_Html;
@@ -11050,15 +9101,13 @@ void generateOutputViaTemplate()
           g_globals.outputDir    = Config_getString(HTML_OUTPUT);
           Dir dir(g_globals.outputDir.str());
           createSubDirs(dir);
-          HtmlEscaper htmlEsc;
-          ctx->setEscapeIntf(Config_getString(HTML_FILE_EXTENSION),&htmlEsc);
-          HtmlSpaceless spl;
-          ctx->setSpacelessIntf(&spl);
+          ctx->setEscapeIntf(Config_getString(HTML_FILE_EXTENSION),std::make_unique<HtmlEscaper>());
+          ctx->setSpacelessIntf(std::make_unique<HtmlSpaceless>());
           ctx->setOutputDirectory(g_globals.outputDir);
           TextStream ts;
-          tpl->render(ts,ctx);
-          e.unload(tpl);
+          tpl->render(ts,ctx.get());
         }
+        e->unload(tpl);
       }
 
       // TODO: clean index before each run...
@@ -11066,8 +9115,8 @@ void generateOutputViaTemplate()
       //if (Config_getBool(GENERATE_LATEX))
       if (0)
       { // render LaTeX output
-        e.setTemplateDir("templates/latex"); // TODO: make template part user configurable
-        Template *tpl = e.loadByName("latexlayout.tpl",1);
+        e->setTemplateDir("templates/latex"); // TODO: make template part user configurable
+        Template *tpl = e->loadByName("latexlayout.tpl",1);
         if (tpl)
         {
           g_globals.outputFormat = ContextOutputFormat_Latex;
@@ -11075,29 +9124,16 @@ void generateOutputViaTemplate()
           g_globals.outputDir    = Config_getString(LATEX_OUTPUT);
           Dir dir(g_globals.outputDir.str());
           createSubDirs(dir);
-          LatexEscaper latexEsc;
-          ctx->setEscapeIntf(".tex",&latexEsc);
-          LatexSpaceless spl;
-          ctx->setSpacelessIntf(&spl);
+          ctx->setEscapeIntf(".tex",std::make_unique<LatexEscaper>());
+          ctx->setSpacelessIntf(std::make_unique<LatexSpaceless>());
           ctx->setOutputDirectory(g_globals.outputDir);
           TextStream ts;
-          tpl->render(ts,ctx);
-          e.unload(tpl);
+          tpl->render(ts,ctx.get());
         }
+        e->unload(tpl);
       }
-
-      // clear all cached data in Definition objects.
-      for (const auto &kv : *Doxygen::symbolMap)
-      {
-        kv.second->setCookie(0);
-      }
-
-      e.destroyContext(ctx);
     }
   }
-#if DEBUG_REF // should be 0, i.e. all objects are deleted
-  printf("==== total ref count %d\n",RefCountedContext::s_totalCount);
-#endif
 }
 
 void generateTemplateFiles(const QCString &templateDir)
index 8621c5f..fa7ab97 100644 (file)
@@ -21,6 +21,7 @@
 #include "classdef.h"
 #include "searchindex.h"
 #include "memberlist.h"
+#include "dotgfxhierarchytable.h"
 
 class Definition;
 
@@ -60,7 +61,6 @@ struct Argument;
 class ArgumentList;
 class MemberInfo;
 class DotNode;
-class DotGfxHierarchyTable;
 
 class MemberGroup;
 class MemberGroupList;
@@ -69,484 +69,411 @@ class MemberVector;
 
 //----------------------------------------------------
 
-#define DEBUG_REF 0
-
-/** @brief Helper class to support reference counting */
-#if DEBUG_REF
-class RefCountedContext
+class ConfigContext : public TemplateStructIntf
 {
   public:
-    RefCountedContext(const char *className) : m_refCount(0)
-    {
-      m_className=className;
-      m_insideRelease = FALSE;
-    }
-    virtual ~RefCountedContext()
-    {
-      if (!m_insideRelease) abort();
-    }
-    int addRef()
-    {
-      ++s_totalCount;
-      printf("%p:%s::addRef()=%d\n",this,qPrint(m_className),m_refCount);
-      return ++m_refCount;
-    }
-    int release()
-    {
-      --s_totalCount;
-      printf("%p:%s::release()=%d\n",this,qPrint(m_className),m_refCount-1);
-      int count = --m_refCount;
-      if (count<=0)
-      {
-        m_insideRelease=TRUE;
-        delete this;
-      }
-      return count;
-    }
-  private:
-    int m_refCount;
-    QCString m_className;
-    bool m_insideRelease;
-  public:
-    static int s_totalCount;
-};
-
-#else // release version
-
-class RefCountedContext
-{
-  public:
-    RefCountedContext(const char *) : m_refCount(0) {}
-    virtual ~RefCountedContext() {}
-    int addRef() { return ++m_refCount; }
-    int release()
-    {
-      int count = --m_refCount;
-      if (count<=0)
-      {
-        delete this;
-      }
-      return count;
-    }
-  private:
-    int m_refCount;
-};
-#endif
-
-
-//----------------------------------------------------
-
-class ConfigContext : public RefCountedContext, public TemplateStructIntf
-{
-  public:
-    static ConfigContext *alloc() { return new ConfigContext; }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ConfigContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     ConfigContext();
-   ~ConfigContext();
+    virtual ~ConfigContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class DoxygenContext : public RefCountedContext, public TemplateStructIntf
+class DoxygenContext : public TemplateStructIntf
 {
   public:
-    static DoxygenContext *alloc() { return new DoxygenContext; }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<DoxygenContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     DoxygenContext();
-    ~DoxygenContext();
+    virtual ~DoxygenContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class TranslateContext : public RefCountedContext, public TemplateStructIntf
+class TranslateContext : public TemplateStructIntf
 {
   public:
-    static TranslateContext *alloc() { return new TranslateContext; }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<TranslateContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     TranslateContext();
-   ~TranslateContext();
+    virtual ~TranslateContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class UsedFilesContext : public RefCountedContext, public TemplateListIntf
+class UsedFilesContext : public TemplateListIntf
 {
   public:
-    static UsedFilesContext *alloc(const ClassDef *cd) { return new UsedFilesContext(cd); }
+    static TemplateListIntfPtr alloc(const ClassDef *cd)
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<UsedFilesContext>(cd)); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
     void addFile(const FileDef *fd);
+    UsedFilesContext(const ClassDef *cd);
+    virtual ~UsedFilesContext();
 
   private:
-    UsedFilesContext(const ClassDef *cd);
-   ~UsedFilesContext();
 
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class IncludeInfoContext : public RefCountedContext, public TemplateStructIntf
+class IncludeInfoContext : public TemplateStructIntf
 {
   public:
-    static IncludeInfoContext *alloc(const IncludeInfo *info,SrcLangExt lang)
-    { return new IncludeInfoContext(info,lang); }
+    static TemplateStructIntfPtr alloc(const IncludeInfo *info,SrcLangExt lang)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<IncludeInfoContext>(info,lang)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     IncludeInfoContext(const IncludeInfo *,SrcLangExt lang);
-   ~IncludeInfoContext();
+    virtual ~IncludeInfoContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class IncludeInfoListContext : public RefCountedContext, public TemplateListIntf
+class IncludeInfoListContext : public TemplateListIntf
 {
   public:
-    static IncludeInfoListContext *alloc(const IncludeInfoList &list,SrcLangExt lang)
-    { return new IncludeInfoListContext(list,lang); }
+    static TemplateListIntfPtr alloc(const IncludeInfoList &list,SrcLangExt lang)
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<IncludeInfoListContext>(list,lang)); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     IncludeInfoListContext(const IncludeInfoList &list,SrcLangExt lang);
-   ~IncludeInfoListContext();
+    virtual ~IncludeInfoListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ClassContext : public RefCountedContext, public TemplateStructIntf
+class ClassContext : public TemplateStructIntf
 {
   public:
-    static ClassContext *alloc(const ClassDef *cd) { return new ClassContext(cd); }
+    static TemplateStructIntfPtr alloc(const ClassDef *cd)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ClassContext>(cd)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     ClassContext(const ClassDef *);
-   ~ClassContext();
+    virtual ~ClassContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 
 //----------------------------------------------------
 
-class ConceptContext : public RefCountedContext, public TemplateStructIntf
+class ConceptContext : public TemplateStructIntf
 {
   public:
-    static ConceptContext *alloc(const ConceptDef *cd) { return new ConceptContext(cd); }
+    static TemplateStructIntfPtr alloc(const ConceptDef *cd)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ConceptContext>(cd)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     ConceptContext(const ConceptDef *);
-   ~ConceptContext();
+    virtual ~ConceptContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class NamespaceContext : public RefCountedContext, public TemplateStructIntf
+class NamespaceContext : public TemplateStructIntf
 {
   public:
-    static NamespaceContext *alloc(const NamespaceDef *nd) { return new NamespaceContext(nd); }
+    static TemplateStructIntfPtr alloc(const NamespaceDef *nd)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<NamespaceContext>(nd)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     NamespaceContext(const NamespaceDef *);
-   ~NamespaceContext();
+    virtual ~NamespaceContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class FileContext : public RefCountedContext, public TemplateStructIntf
+class FileContext : public TemplateStructIntf
 {
   public:
-    static FileContext *alloc(const FileDef *fd) { return new FileContext(fd); }
+    static TemplateStructIntfPtr alloc(const FileDef *fd)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<FileContext>(fd)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     FileContext(const FileDef *);
-   ~FileContext();
+    virtual ~FileContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 //----------------------------------------------------
 
-class DirContext : public RefCountedContext, public TemplateStructIntf
+class DirContext : public TemplateStructIntf
 {
   public:
-    static DirContext *alloc(const DirDef *dd) { return new DirContext(dd); }
+    static TemplateStructIntfPtr alloc(const DirDef *dd)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<DirContext>(dd)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     DirContext(const DirDef *);
-   ~DirContext();
+    virtual ~DirContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 
 //----------------------------------------------------
 
-class PageContext : public RefCountedContext, public TemplateStructIntf
+class PageContext : public TemplateStructIntf
 {
   public:
-    static PageContext *alloc(const PageDef *pd,bool isMainPage,bool isExample) { return new PageContext(pd,isMainPage,isExample); }
+    static TemplateStructIntfPtr alloc(const PageDef *pd,bool isMainPage,bool isExample)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<PageContext>(pd,isMainPage,isExample)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     PageContext(const PageDef *,bool isMainPage,bool isExample);
-   ~PageContext();
+    virtual ~PageContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class MemberContext : public RefCountedContext, public TemplateStructIntf
+class MemberContext : public TemplateStructIntf
 {
   public:
-    static MemberContext *alloc(const MemberDef *md) { return new MemberContext(md); }
+    static TemplateStructIntfPtr alloc(const MemberDef *md)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<MemberContext>(md)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     MemberContext(const MemberDef *);
-   ~MemberContext();
+    virtual ~MemberContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 
 //----------------------------------------------------
 
-class ModuleContext : public RefCountedContext, public TemplateStructIntf
+class ModuleContext : public TemplateStructIntf
 {
   public:
-    static ModuleContext *alloc(const GroupDef *gd) { return new ModuleContext(gd); }
+    static TemplateStructIntfPtr alloc(const GroupDef *gd)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ModuleContext>(gd)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     ModuleContext(const GroupDef *);
-   ~ModuleContext();
+    virtual ~ModuleContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ClassListContext : public RefCountedContext, public TemplateListIntf
+class ClassListContext : public TemplateListIntf
 {
   public:
-    static ClassListContext *alloc() { return new ClassListContext; }
+    static TemplateListIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ClassListContext>()); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     ClassListContext();
-   ~ClassListContext();
+    virtual ~ClassListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ClassIndexContext : public RefCountedContext, public TemplateStructIntf
+class ClassIndexContext : public TemplateStructIntf
 {
   public:
-    static ClassIndexContext *alloc() { return new ClassIndexContext; }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ClassIndexContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     ClassIndexContext();
-   ~ClassIndexContext();
+    virtual ~ClassIndexContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class InheritanceGraphContext : public RefCountedContext, public TemplateStructIntf
+class InheritanceGraphContext : public TemplateStructIntf
 {
   public:
-    static InheritanceGraphContext *alloc(DotGfxHierarchyTable *hierarchy,DotNode *n,int id)
-    { return new InheritanceGraphContext(hierarchy,n,id); }
+    static TemplateStructIntfPtr alloc(DotGfxHierarchyTablePtr hierarchy,DotNode *n,int id)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<InheritanceGraphContext>(hierarchy,n,id)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+
+    InheritanceGraphContext(DotGfxHierarchyTablePtr hierarchy,DotNode *n,int id);
+    virtual ~InheritanceGraphContext();
 
   private:
-    InheritanceGraphContext(DotGfxHierarchyTable *hierarchy,DotNode *n,int id);
-   ~InheritanceGraphContext();
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ClassInheritanceNodeContext : public RefCountedContext, public TemplateStructIntf
+class ClassInheritanceNodeContext : public TemplateStructIntf
 {
   public:
-    static ClassInheritanceNodeContext *alloc(const ClassDef *cd)
-    { return new ClassInheritanceNodeContext(cd); }
+    static TemplateStructIntfPtr alloc(const ClassDef *cd)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ClassInheritanceNodeContext>(cd)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
     void addChildren(const BaseClassList &bcl,bool hideSuper);
+    ClassInheritanceNodeContext(const ClassDef *);
+    virtual ~ClassInheritanceNodeContext();
 
   private:
-    ClassInheritanceNodeContext(const ClassDef *);
-   ~ClassInheritanceNodeContext();
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ClassInheritanceContext : public RefCountedContext, public TemplateListIntf
+class ClassInheritanceContext : public TemplateListIntf
 {
   public:
-    static ClassInheritanceContext *alloc() { return new ClassInheritanceContext; }
+    static TemplateListIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ClassInheritanceContext>()); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     ClassInheritanceContext();
-   ~ClassInheritanceContext();
+    virtual ~ClassInheritanceContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ClassHierarchyContext : public RefCountedContext, public TemplateStructIntf
+class ClassHierarchyContext : public TemplateStructIntf
 {
   public:
-    static ClassHierarchyContext *alloc() { return new ClassHierarchyContext; }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ClassHierarchyContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     ClassHierarchyContext();
-   ~ClassHierarchyContext();
+    virtual ~ClassHierarchyContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
@@ -563,53 +490,50 @@ enum class ContextTreeType
   Example              // ExampleTreeContext
 };
 
-class NestingNodeContext : public RefCountedContext, public TemplateStructIntf
+class NestingNodeContext : public TemplateStructIntf
 {
   public:
-    static NestingNodeContext *alloc(const NestingNodeContext *parent,ContextTreeType type,
+    static TemplateStructIntfPtr alloc(const NestingNodeContext *parent,ContextTreeType type,
                                      const Definition *def,
                                      int index,int level,
                                      bool addClasses,bool addConcepts,
                                      bool inherit,bool hideSuper,
                                      ClassDefSet &visitedClasses)
-    { return new NestingNodeContext(parent,type,def,index,level,addClasses,addConcepts,
-                                    inherit,hideSuper,visitedClasses); }
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<NestingNodeContext>
+             (parent,type,def,index,level,addClasses,addConcepts,inherit,hideSuper,visitedClasses)); }
 
     QCString id() const;
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     NestingNodeContext(const NestingNodeContext *parent,
                        ContextTreeType type,
                        const Definition *,int index,int level,
                        bool addClasses,bool addConcepts,
                        bool inherit,bool hideSuper,
                        ClassDefSet &visitedClasses);
-   ~NestingNodeContext();
+    virtual ~NestingNodeContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class NestingContext : public RefCountedContext, public TemplateListIntf
+class NestingContext : public TemplateListIntf
 {
   public:
 
-    static NestingContext *alloc(const NestingNodeContext *parent,ContextTreeType type,int level)
-    { return new NestingContext(parent,type,level); }
+    static TemplateListIntfPtr alloc(const NestingNodeContext *parent,ContextTreeType type,int level)
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<NestingContext>(parent,type,level)); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
     void addNamespaces(const NamespaceLinkedMap &nsLinkedMap,bool rootOnly,bool addClasses,bool addConcepts,ClassDefSet &visitedClasses);
     void addNamespaces(const NamespaceLinkedRefMap &nsLinkedMap,bool rootOnly,bool addClasses,bool addConcepts,ClassDefSet &visitedClasses);
@@ -629,857 +553,842 @@ class NestingContext : public RefCountedContext, public TemplateListIntf
     void addDerivedClasses(const BaseClassList &bcl,bool hideSuper,ClassDefSet &visitedClasses);
     void addMembers(const MemberVector &mv,ClassDefSet &visitedClasses);
 
-  private:
     NestingContext(const NestingNodeContext *parent,ContextTreeType type,int level);
-   ~NestingContext();
+    virtual ~NestingContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ClassTreeContext : public RefCountedContext, public TemplateStructIntf
+class ClassTreeContext : public TemplateStructIntf
 {
   public:
-    static ClassTreeContext *alloc() { return new ClassTreeContext; }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ClassTreeContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     ClassTreeContext();
-   ~ClassTreeContext();
+    virtual ~ClassTreeContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ConceptListContext : public RefCountedContext, public TemplateListIntf
+class ConceptListContext : public TemplateListIntf
 {
   public:
-    static ConceptListContext *alloc() { return new ConceptListContext; }
+    static TemplateListIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ConceptListContext>()); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     ConceptListContext();
-   ~ConceptListContext();
+    virtual ~ConceptListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class NamespaceListContext : public RefCountedContext, public TemplateListIntf
+class NamespaceListContext : public TemplateListIntf
 {
   public:
-    static NamespaceListContext *alloc() { return new NamespaceListContext; }
+    static TemplateListIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<NamespaceListContext>()); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     NamespaceListContext();
-   ~NamespaceListContext();
+    virtual ~NamespaceListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class NamespaceTreeContext : public RefCountedContext, public TemplateStructIntf
+class NamespaceTreeContext : public TemplateStructIntf
 {
   public:
-    static NamespaceTreeContext *alloc() { return new NamespaceTreeContext; }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<NamespaceTreeContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     NamespaceTreeContext();
-   ~NamespaceTreeContext();
+    virtual ~NamespaceTreeContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class DirListContext : public RefCountedContext, public TemplateListIntf
+class DirListContext : public TemplateListIntf
 {
   public:
-    static DirListContext *alloc() { return new DirListContext; }
+    static TemplateListIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<DirListContext>()); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     DirListContext();
-   ~DirListContext();
+    virtual ~DirListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class FileListContext : public RefCountedContext, public TemplateListIntf
+class FileListContext : public TemplateListIntf
 {
   public:
-    static FileListContext *alloc() { return new FileListContext; }
+    static TemplateListIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<FileListContext>()); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     FileListContext();
-   ~FileListContext();
+    virtual ~FileListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class FileTreeContext : public RefCountedContext, public TemplateStructIntf
+class FileTreeContext : public TemplateStructIntf
 {
   public:
-    static FileTreeContext *alloc() { return new FileTreeContext; }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<FileTreeContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     FileTreeContext();
-   ~FileTreeContext();
+    virtual ~FileTreeContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class PageListContext : public RefCountedContext, public TemplateListIntf
+class PageListContext : public TemplateListIntf
 {
   public:
-    static PageListContext *alloc(const PageLinkedMap &pages) { return new PageListContext(pages); }
+    static TemplateListIntfPtr alloc(const PageLinkedMap &pages)
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<PageListContext>(pages)); }
 
     // TemplateListIntf methods
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
     void addPages(const PageLinkedMap &pages);
 
-  private:
     PageListContext(const PageLinkedMap &pages);
-   ~PageListContext();
+    virtual ~PageListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class PageTreeContext : public RefCountedContext, public TemplateStructIntf
+class PageTreeContext : public TemplateStructIntf
 {
   public:
-    static PageTreeContext *alloc(const PageLinkedMap &pages) { return new PageTreeContext(pages); }
+    static TemplateStructIntfPtr alloc(const PageLinkedMap &pages)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<PageTreeContext>(pages)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     PageTreeContext(const PageLinkedMap &pages);
-   ~PageTreeContext();
+    virtual ~PageTreeContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ModuleNodeContext : public RefCountedContext, public TemplateStructIntf
+class ModuleNodeContext : public TemplateStructIntf
 {
   public:
-    static ModuleNodeContext *alloc(const GroupDef *gd) { return new ModuleNodeContext(gd); }
+    static TemplateStructIntfPtr alloc(const GroupDef *gd)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ModuleNodeContext>(gd)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     ModuleNodeContext(const GroupDef *);
-   ~ModuleNodeContext();
+    virtual ~ModuleNodeContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ModuleListContext : public RefCountedContext, public TemplateListIntf
+class ModuleListContext : public TemplateListIntf
 {
   public:
-    static ModuleListContext *alloc() { return new ModuleListContext(); }
+    static TemplateListIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ModuleListContext>()); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
     void addModules(const GroupLinkedMap &);
     void addModules(const GroupList &);
 
-  private:
     ModuleListContext();
-   ~ModuleListContext();
+    virtual ~ModuleListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ConceptTreeContext : public RefCountedContext, public TemplateStructIntf
+class ConceptTreeContext : public TemplateStructIntf
 {
   public:
-    static ConceptTreeContext *alloc() { return new ConceptTreeContext(); }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ConceptTreeContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     ConceptTreeContext();
-   ~ConceptTreeContext();
+    virtual ~ConceptTreeContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ModuleTreeContext : public RefCountedContext, public TemplateStructIntf
+class ModuleTreeContext : public TemplateStructIntf
 {
   public:
-    static ModuleTreeContext *alloc() { return new ModuleTreeContext(); }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ModuleTreeContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     ModuleTreeContext();
-   ~ModuleTreeContext();
+    virtual ~ModuleTreeContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ExampleListContext : public RefCountedContext, public TemplateListIntf
+class ExampleListContext : public TemplateListIntf
 {
   public:
-    static ExampleListContext *alloc() { return new ExampleListContext; }
+    static TemplateListIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ExampleListContext>()); }
 
     // TemplateListIntf methods
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     ExampleListContext();
-   ~ExampleListContext();
+    virtual ~ExampleListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
 
-class ExampleTreeContext : public RefCountedContext, public TemplateStructIntf
+class ExampleTreeContext : public TemplateStructIntf
 {
   public:
-    static ExampleTreeContext *alloc() { return new ExampleTreeContext; }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ExampleTreeContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     ExampleTreeContext();
-   ~ExampleTreeContext();
+    virtual ~ExampleTreeContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class GlobalsIndexContext : public RefCountedContext, public TemplateStructIntf
+class GlobalsIndexContext : public TemplateStructIntf
 {
   public:
-    static GlobalsIndexContext *alloc() { return new GlobalsIndexContext(); }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<GlobalsIndexContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     GlobalsIndexContext();
-   ~GlobalsIndexContext();
+    virtual ~GlobalsIndexContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ClassMembersIndexContext : public RefCountedContext, public TemplateStructIntf
+class ClassMembersIndexContext : public TemplateStructIntf
 {
   public:
-    static ClassMembersIndexContext *alloc() { return new ClassMembersIndexContext(); }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ClassMembersIndexContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     ClassMembersIndexContext();
-   ~ClassMembersIndexContext();
+    virtual ~ClassMembersIndexContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class NamespaceMembersIndexContext : public RefCountedContext, public TemplateStructIntf
+class NamespaceMembersIndexContext : public TemplateStructIntf
 {
   public:
-    static NamespaceMembersIndexContext *alloc() { return new NamespaceMembersIndexContext(); }
+    static TemplateStructIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<NamespaceMembersIndexContext>()); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     NamespaceMembersIndexContext();
-   ~NamespaceMembersIndexContext();
+    virtual ~NamespaceMembersIndexContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class NavPathElemContext : public RefCountedContext, public TemplateStructIntf
+class NavPathElemContext : public TemplateStructIntf
 {
   public:
-    static NavPathElemContext *alloc(const Definition *def) { return new NavPathElemContext(def); }
+    static TemplateStructIntfPtr alloc(const Definition *def)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<NavPathElemContext>(def)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     NavPathElemContext(const Definition *def);
-   ~NavPathElemContext();
+    virtual ~NavPathElemContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 
 //----------------------------------------------------
 
-class InheritanceNodeContext : public RefCountedContext, public TemplateStructIntf
+class InheritanceNodeContext : public TemplateStructIntf
 {
   public:
-    static InheritanceNodeContext *alloc(const ClassDef *cd,const QCString &name)
-    { return new InheritanceNodeContext(cd,name); }
+    static TemplateStructIntfPtr alloc(const ClassDef *cd,const QCString &name)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<InheritanceNodeContext>(cd,name)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     InheritanceNodeContext(const ClassDef *cd,const QCString &name);
-   ~InheritanceNodeContext();
+    virtual ~InheritanceNodeContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class InheritanceListContext : public RefCountedContext, public TemplateListIntf
+class InheritanceListContext : public TemplateListIntf
 {
   public:
-    static InheritanceListContext *alloc(const BaseClassList &list,bool baseClasses)
-    { return new InheritanceListContext(list,baseClasses); }
+    static TemplateListIntfPtr alloc(const BaseClassList &list,bool baseClasses)
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<InheritanceListContext>(list,baseClasses)); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     InheritanceListContext(const BaseClassList &list,bool baseClasses);
-   ~InheritanceListContext();
+    virtual ~InheritanceListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class MemberListContext : public RefCountedContext, public TemplateListIntf
+class MemberListContext : public TemplateListIntf
 {
   public:
-    static MemberListContext *alloc()
-    { return new MemberListContext; }
-    static MemberListContext *alloc(const MemberList *ml)
-    { return new MemberListContext(ml); }
-    static MemberListContext *alloc(const MemberVector &ml)
-    { return new MemberListContext(ml); }
+    static TemplateListIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<MemberListContext>()); }
+    static TemplateListIntfPtr alloc(const MemberList *ml)
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<MemberListContext>(ml)); }
+    static TemplateListIntfPtr alloc(const MemberVector &ml)
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<MemberListContext>(ml)); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     MemberListContext();
     MemberListContext(const MemberList *ml);
     MemberListContext(const MemberVector &ml);
-   ~MemberListContext();
+    virtual ~MemberListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class MemberGroupInfoContext : public RefCountedContext, public TemplateStructIntf
+class MemberGroupInfoContext : public TemplateStructIntf
 {
   public:
-    static MemberGroupInfoContext *alloc(const Definition *def,const QCString &relPath,const MemberGroup *mg)
-    { return new MemberGroupInfoContext(def,relPath,mg); }
+    static TemplateStructIntfPtr alloc(const Definition *def,const QCString &relPath,const MemberGroup *mg)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<MemberGroupInfoContext>(def,relPath,mg)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     MemberGroupInfoContext(const Definition *def,const QCString &relPath,const MemberGroup *mg);
-   ~MemberGroupInfoContext();
+    virtual ~MemberGroupInfoContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class MemberGroupListContext : public RefCountedContext, public TemplateListIntf
+class MemberGroupListContext : public TemplateListIntf
 {
   public:
-    static MemberGroupListContext *alloc()
-    { return new MemberGroupListContext; }
-    static MemberGroupListContext *alloc(const Definition *def,const QCString &relPath,const MemberGroupRefList &list)
-    { return new MemberGroupListContext(def,relPath,list); }
-    static MemberGroupListContext *alloc(const Definition *def,const QCString &relPath,const MemberGroupList &list,bool subGrouping)
-    { return new MemberGroupListContext(def,relPath,list,subGrouping); }
+    static TemplateListIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<MemberGroupListContext>()); }
+    static TemplateListIntfPtr alloc(const Definition *def,const QCString &relPath,const MemberGroupRefList &list)
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<MemberGroupListContext>(def,relPath,list)); }
+    static TemplateListIntfPtr alloc(const Definition *def,const QCString &relPath,const MemberGroupList &list,bool subGrouping)
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<MemberGroupListContext>(def,relPath,list,subGrouping)); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     MemberGroupListContext();
     MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupRefList &list);
     MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupList &list,bool subGrouping);
-   ~MemberGroupListContext();
+    virtual ~MemberGroupListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 
 //----------------------------------------------------
 
-class MemberListInfoContext : public RefCountedContext, public TemplateStructIntf
+class MemberListInfoContext : public TemplateStructIntf
 {
   public:
-    static MemberListInfoContext *alloc(const Definition *def,const QCString &relPath,
+    static TemplateStructIntfPtr 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); }
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<MemberListInfoContext>(def,relPath,ml,title,subtitle)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     MemberListInfoContext(const Definition *def,const QCString &relPath,
                           const MemberList *ml,const QCString &title,
                           const QCString &subtitle=QCString());
-   ~MemberListInfoContext();
+    virtual ~MemberListInfoContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class MemberInfoContext : public RefCountedContext, public TemplateStructIntf
+class MemberInfoContext : public TemplateStructIntf
 {
   public:
-    static MemberInfoContext *alloc(const MemberInfo *mi) { return new MemberInfoContext(mi); }
+    static TemplateStructIntfPtr alloc(const MemberInfo *mi)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<MemberInfoContext>(mi)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     MemberInfoContext(const MemberInfo *mi);
-   ~MemberInfoContext();
+    virtual ~MemberInfoContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class InheritedMemberInfoContext : public RefCountedContext, public TemplateStructIntf
+class InheritedMemberInfoContext : public TemplateStructIntf
 {
   public:
-    static InheritedMemberInfoContext *alloc(const ClassDef *cd,const MemberList *ml,const QCString &title)
-    { return new InheritedMemberInfoContext(cd,ml,title); }
+    static TemplateStructIntfPtr alloc(const ClassDef *cd,std::unique_ptr<MemberList> &&ml,const QCString &title)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<InheritedMemberInfoContext>(cd,std::move(ml),title)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+
+    InheritedMemberInfoContext(const ClassDef *cd,std::unique_ptr<MemberList> &&ml,const QCString &title);
+    virtual ~InheritedMemberInfoContext();
 
   private:
-    InheritedMemberInfoContext(const ClassDef *cd,const MemberList *ml,const QCString &title);
-   ~InheritedMemberInfoContext();
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class InheritedMemberInfoListContext : public RefCountedContext, public TemplateListIntf
+class InheritedMemberInfoListContext : public TemplateListIntf
 {
   public:
-    static InheritedMemberInfoListContext *alloc() { return new InheritedMemberInfoListContext; }
+    static TemplateListIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<InheritedMemberInfoListContext>()); }
     void addMemberList(const ClassDef *cd,MemberListType lt,const QCString &title,bool additionalList=TRUE);
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     InheritedMemberInfoListContext();
-   ~InheritedMemberInfoListContext();
+    virtual ~InheritedMemberInfoListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class AllMembersListContext : public RefCountedContext, public TemplateListIntf
+class AllMembersListContext : public TemplateListIntf
 {
   public:
-    static AllMembersListContext *alloc(const MemberNameInfoLinkedMap &ml)
-    { return new AllMembersListContext(ml); }
+    static TemplateListIntfPtr alloc(const MemberNameInfoLinkedMap &ml)
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<AllMembersListContext>(ml)); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     AllMembersListContext(const MemberNameInfoLinkedMap &ml);
-   ~AllMembersListContext();
+    virtual ~AllMembersListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ArgumentContext : public RefCountedContext, public TemplateStructIntf
+class ArgumentContext : public TemplateStructIntf
 {
   public:
-    static ArgumentContext *alloc(const Argument &arg,const Definition *def,const QCString &relPath)
-    { return new ArgumentContext(arg,def,relPath); }
+    static TemplateStructIntfPtr alloc(const Argument &arg,const Definition *def,const QCString &relPath)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<ArgumentContext>(arg,def,relPath)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     ArgumentContext(const Argument &arg,const Definition *def,const QCString &relPath);
-   ~ArgumentContext();
+    virtual ~ArgumentContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class ArgumentListContext : public RefCountedContext, public TemplateListIntf
+class ArgumentListContext : public TemplateListIntf
 {
   public:
-    static ArgumentListContext *alloc() { return new ArgumentListContext; }
-    static ArgumentListContext *alloc(const ArgumentList &al,const Definition *def,const QCString &relPath)
-    { return new ArgumentListContext(al,def,relPath); }
+    static TemplateListIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ArgumentListContext>()); }
+    static TemplateListIntfPtr alloc(const ArgumentList &al,const Definition *def,const QCString &relPath)
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<ArgumentListContext>(al,def,relPath)); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     ArgumentListContext();
     ArgumentListContext(const ArgumentList &al,const Definition *def,const QCString &relPath);
-   ~ArgumentListContext();
+    virtual ~ArgumentListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class SymbolContext : public RefCountedContext, public TemplateStructIntf
+class SymbolContext : public TemplateStructIntf
 {
   public:
-    static SymbolContext *alloc(const Definition *def,const Definition *prev,const Definition *next)
-    { return new SymbolContext(def,prev,next); }
+    static TemplateStructIntfPtr alloc(const Definition *def,const Definition *prev,const Definition *next)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<SymbolContext>(def,prev,next)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     SymbolContext(const Definition *def,const Definition *prev,const Definition *next);
-   ~SymbolContext();
+    virtual ~SymbolContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class SymbolListContext : public RefCountedContext, public TemplateListIntf
+class SymbolListContext : public TemplateListIntf
 {
   public:
-    static SymbolListContext *alloc(const SearchIndexList::const_iterator &start,
+    static TemplateListIntfPtr alloc(const SearchIndexList::const_iterator &start,
                                     const SearchIndexList::const_iterator &end)
-    { return new SymbolListContext(start,end); }
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<SymbolListContext>(start,end)); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     SymbolListContext(const SearchIndexList::const_iterator &start,
                       const SearchIndexList::const_iterator &end);
-   ~SymbolListContext();
+    virtual ~SymbolListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class SymbolGroupContext : public RefCountedContext, public TemplateStructIntf
+class SymbolGroupContext : public TemplateStructIntf
 {
   public:
-    static SymbolGroupContext *alloc(const SearchIndexList::const_iterator &start,
+    static TemplateStructIntfPtr alloc(const SearchIndexList::const_iterator &start,
                                      const SearchIndexList::const_iterator &end)
-    { return new SymbolGroupContext(start,end); }
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<SymbolGroupContext>(start,end)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     SymbolGroupContext(const SearchIndexList::const_iterator &start,
                        const SearchIndexList::const_iterator &end);
-   ~SymbolGroupContext();
+    virtual ~SymbolGroupContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class SymbolGroupListContext : public RefCountedContext, public TemplateListIntf
+class SymbolGroupListContext : public TemplateListIntf
 {
   public:
-    static SymbolGroupListContext *alloc(const SearchIndexList &sil)
-    { return new SymbolGroupListContext(sil); }
+    static TemplateListIntfPtr alloc(const SearchIndexList &sil)
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<SymbolGroupListContext>(sil)); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     SymbolGroupListContext(const SearchIndexList &sil);
-   ~SymbolGroupListContext();
+    virtual ~SymbolGroupListContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class SymbolIndexContext : public RefCountedContext, public TemplateStructIntf
+class SymbolIndexContext : public TemplateStructIntf
 {
   public:
-    static SymbolIndexContext *alloc(const std::string &letter,
+    static TemplateStructIntfPtr alloc(const std::string &letter,
                                      const SearchIndexList &sl,const QCString &name)
-    { return new SymbolIndexContext(letter,sl,name); }
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<SymbolIndexContext>(letter,sl,name)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     SymbolIndexContext(const std::string &letter,const SearchIndexList &sl,const QCString &name);
-   ~SymbolIndexContext();
+    virtual ~SymbolIndexContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class SymbolIndicesContext : public RefCountedContext, public TemplateListIntf
+class SymbolIndicesContext : public TemplateListIntf
 {
   public:
-    static SymbolIndicesContext *alloc(const SearchIndexInfo &info)
-    { return new SymbolIndicesContext(info); }
+    static TemplateListIntfPtr alloc(const SearchIndexInfo &info)
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<SymbolIndicesContext>(info)); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     SymbolIndicesContext(const SearchIndexInfo &info);
-   ~SymbolIndicesContext();
+    virtual ~SymbolIndicesContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class SearchIndexContext : public RefCountedContext, public TemplateStructIntf
+class SearchIndexContext : public TemplateStructIntf
 {
   public:
-    static SearchIndexContext *alloc(const SearchIndexInfo &info)
-    { return new SearchIndexContext(info); }
+    static TemplateStructIntfPtr alloc(const SearchIndexInfo &info)
+    { return std::static_pointer_cast<TemplateStructIntf>(std::make_shared<SearchIndexContext>(info)); }
 
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
 
-  private:
     SearchIndexContext(const SearchIndexInfo &info);
-   ~SearchIndexContext();
+    virtual ~SearchIndexContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
 
-class SearchIndicesContext : public RefCountedContext, public TemplateListIntf
+class SearchIndicesContext : public TemplateListIntf
 {
   public:
-    static SearchIndicesContext *alloc() { return new SearchIndicesContext; }
+    static TemplateListIntfPtr alloc()
+    { return std::static_pointer_cast<TemplateListIntf>(std::make_shared<SearchIndicesContext>()); }
 
     // TemplateListIntf
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef()  { return RefCountedContext::addRef(); }
-    virtual int release() { return RefCountedContext::release(); }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-  private:
     SearchIndicesContext();
-   ~SearchIndicesContext();
+    virtual ~SearchIndicesContext();
+
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //----------------------------------------------------
index 3e3f503..2e578b0 100644 (file)
 %option extra-type="struct declinfoYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -81,21 +85,23 @@ static yy_size_t yyread(char *buf,yy_size_t max_size, yyscan_t yyscanner);
  */
 #undef YY_INPUT
 #define        YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner);
+
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#define LEX_NO_INPUT_FILENAME
+#include "doxygen_lex.h"
 %}
 
 B       [ \t]
 Bopt    {B}*
 ID     ([$a-z_A-Z\x80-\xFF][$a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+)
 
-%x      Start
+%x  Start
 %x     Template
 %x     ReadArgs
 %x     Operator
-%x     FuncPtr
-%x     EndTemplate
-%x     StripTempArgs
-%x     SkipSharp
-%x      ReadExceptions
+%x     DeclType
+%x  ReadExceptions
 
 %%
 
@@ -159,10 +165,28 @@ ID        ([$a-z_A-Z\x80-\xFF][$a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+)
 <Start>{B}*")"                 {
                                  yyextra->type+=")";
                                }
+<Start>{B}*"decltype"/{B}*"("  {
+                                         yyextra->roundCount=0;
+                                         yyextra->type="decltype";
+                                         BEGIN(DeclType);
+                                       }
+<DeclType>{B}*"("      {
+                                               ++yyextra->roundCount;
+                                               yyextra->type+="(";
+                                       }
+<DeclType>{B}*")"      {
+                                               yyextra->type+=")";
+                                               if (--yyextra->roundCount == 0) {
+                                                       BEGIN(Start);
+                                               }
+                                       }
+<DeclType>.    {
+                                               yyextra->type+=yytext;
+                                       }
 <Start>{B}*"("                 { // TODO: function pointers
-                                 yyextra->args+="(";
-                                 BEGIN(ReadArgs);
-                               }
+                                               yyextra->args+="(";
+                                               BEGIN(ReadArgs);
+                                       }
 <Start>{B}*"["                 {
                                  yyextra->args+="[";
                                  BEGIN(ReadArgs);
@@ -361,7 +385,7 @@ void parseFuncDecl(const QCString &decl,const SrcLangExt lang,QCString &cl,QCStr
   a=removeRedundantWhiteSpace(yyextra->args);
   exc=removeRedundantWhiteSpace(yyextra->exceptionString);
   
-  if (!t.isEmpty() && t.at(t.length()-1)==')') // for function pointers
+  if (!t.isEmpty() && !t.startsWith("decltype") && t.at(t.length()-1)==')') // for function pointers
   {
     a.prepend(")");
     t=t.left(t.length()-1);
index b1a1b15..121b21b 100644 (file)
 %option extra-type="struct defargsYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -111,6 +115,11 @@ static bool nameIsActuallyPartOfType(QCString &name);
 #undef YY_INPUT
 #define        YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#define LEX_NO_INPUT_FILENAME
+#include "doxygen_lex.h"
+
 %}
 
 B       [ \t]
index dae7ce2..08ed32e 100644 (file)
@@ -85,7 +85,6 @@ class DefinitionImpl::IMPL
     QCString symbolName;
     int defLine;
     int defColumn;
-    Definition::Cookie *cookie;
 
     mutable MemberVector referencesMembers;
     mutable MemberVector referencedByMembers;
@@ -123,7 +122,7 @@ void DefinitionImpl::IMPL::init(const QCString &df, const QCString &n)
   {
     localName=n;
   }
-  //printf("m_localName=%s\n",qPrint(m_localName));
+  //printf("localName=%s\n",qPrint(localName));
 
   brief           = 0;
   details         = 0;
@@ -135,7 +134,6 @@ void DefinitionImpl::IMPL::init(const QCString &df, const QCString &n)
   hidden          = FALSE;
   isArtificial    = FALSE;
   lang            = SrcLangExt_Unknown;
-  cookie          = 0;
 }
 
 void DefinitionImpl::setDefFile(const QCString &df,int defLine,int defCol)
@@ -490,10 +488,10 @@ void DefinitionImpl::setDocumentation(const QCString &d,const QCString &docFile,
 
 void DefinitionImpl::_setBriefDescription(const QCString &b,const QCString &briefFile,int briefLine)
 {
-  static QCString outputLanguage = Config_getEnum(OUTPUT_LANGUAGE);
-  static bool needsDot = outputLanguage!="Japanese" &&
-                         outputLanguage!="Chinese" &&
-                         outputLanguage!="Korean";
+  static OUTPUT_LANGUAGE_t outputLanguage = Config_getEnum(OUTPUT_LANGUAGE);
+  static bool needsDot = outputLanguage!=OUTPUT_LANGUAGE_t::Japanese &&
+                         outputLanguage!=OUTPUT_LANGUAGE_t::Chinese &&
+                         outputLanguage!=OUTPUT_LANGUAGE_t::Korean;
   QCString brief = b;
   brief = brief.stripWhiteSpace();
   brief = stripLeadingAndTrailingEmptyLines(brief,briefLine);
@@ -1356,13 +1354,13 @@ QCString DefinitionImpl::navigationPathAsString() const
     if (m_impl->def->definitionType()==Definition::TypeGroup &&
         !toGroupDef(m_impl->def)->groupTitle().isEmpty())
     {
-      result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+
+      result+="<a class=\"el\" href=\"$relpath^"+addHtmlExtensionIfMissing(m_impl->def->getOutputFileBase())+"\">"+
               convertToHtml(toGroupDef(m_impl->def)->groupTitle())+"</a>";
     }
     else if (m_impl->def->definitionType()==Definition::TypePage &&
              toPageDef(m_impl->def)->hasTitle())
     {
-      result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+
+      result+="<a class=\"el\" href=\"$relpath^"+addHtmlExtensionIfMissing(m_impl->def->getOutputFileBase())+"\">"+
             convertToHtml((toPageDef(m_impl->def))->title())+"</a>";
     }
     else if (m_impl->def->definitionType()==Definition::TypeClass)
@@ -1372,13 +1370,13 @@ QCString DefinitionImpl::navigationPathAsString() const
       {
         name = name.left(name.length()-2);
       }
-      result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension;
+      result+="<a class=\"el\" href=\"$relpath^"+addHtmlExtensionIfMissing(m_impl->def->getOutputFileBase());
       if (!m_impl->def->anchor().isEmpty()) result+="#"+m_impl->def->anchor();
       result+="\">"+convertToHtml(name)+"</a>";
     }
     else
     {
-      result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+
+      result+="<a class=\"el\" href=\"$relpath^"+addHtmlExtensionIfMissing(m_impl->def->getOutputFileBase())+"\">"+
               convertToHtml(locName)+"</a>";
     }
   }
@@ -1476,7 +1474,6 @@ void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const
       level--;
     }
     if (level <= maxLevel && inLi[level]) ol.writeString("</li>\n");
-    inLi[level]=false;
     ol.writeString("</ul>\n");
     ol.writeString("</div>\n");
     ol.popGeneratorState();
@@ -1531,7 +1528,6 @@ void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const
       ol.writeString("</tocdiv>\n");
       level--;
     }
-    inLi[level]=FALSE;
     ol.writeString("    </toc>\n");
     ol.popGeneratorState();
   }
@@ -1899,17 +1895,6 @@ int DefinitionImpl::getDefColumn() const
   return m_impl->defColumn;
 }
 
-void DefinitionImpl::setCookie(Definition::Cookie *cookie) const
-{
-  delete m_impl->cookie;
-  m_impl->cookie = cookie;
-}
-
-Definition::Cookie *DefinitionImpl::cookie() const
-{
-  return m_impl->cookie;
-}
-
 void DefinitionImpl::writeQuickMemberLinks(OutputList &,const MemberDef *) const
 {
 }
index 8bf4de9..ac91201 100644 (file)
@@ -23,8 +23,8 @@
 #include "types.h"
 #include "reflist.h"
 
-#if defined(_WIN32) && !defined(__CYGWIN__)
-// To disable 'inherits via dominance' warnings.
+#ifdef _MSC_VER
+// To disable 'inherits via dominance' warnings with MSVC.
 // See also https://stackoverflow.com/a/14487243/784672
 #pragma warning( disable: 4250 )
 #endif
@@ -289,12 +289,6 @@ class Definition
     virtual QCString pathFragment() 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;
index a7b3aad..a620b81 100644 (file)
@@ -117,8 +117,6 @@ class DefinitionImpl
     void setLocalName(const QCString &name);
     void addSectionsToIndex();
     void writeToc(OutputList &ol, const LocalToc &lt) const;
-    void setCookie(Definition::Cookie *cookie) const;
-    Definition::Cookie *cookie() const;
     void computeTooltip();
     void _setSymbolName(const QCString &name);
     QCString _symbolName() const;
@@ -275,10 +273,6 @@ class DefinitionMixin : public Base
     { m_impl.addSectionsToIndex(); }
     virtual void writeToc(OutputList &ol, const LocalToc &lt) const
     { m_impl.writeToc(ol,lt); }
-    virtual void setCookie(Definition::Cookie *cookie) const
-    { m_impl.setCookie(cookie); }
-    virtual Definition::Cookie *cookie() const
-    { return m_impl.cookie(); }
     virtual void computeTooltip()
     { m_impl.computeTooltip(); }
     virtual void _setSymbolName(const QCString &name)
@@ -319,7 +313,7 @@ class DefinitionAliasMixin : public Base
 {
   public:
     DefinitionAliasMixin(const Definition *scope,const Definition *alias)
-      : m_impl(this,scope,alias), m_scope(scope), m_alias(alias), m_cookie(0) {}
+      : m_impl(this,scope,alias), m_scope(scope), m_alias(alias) {}
 
     void init() { m_impl.init(); }
     void deinit() { m_impl.deinit(); }
@@ -437,14 +431,11 @@ class DefinitionAliasMixin : public Base
     virtual DefinitionMutable *toDefinitionMutable_() { return 0; }
     virtual const DefinitionImpl *toDefinitionImpl_() const { return 0; }
 
-    virtual void setCookie(Definition::Cookie *cookie) const { delete m_cookie; m_cookie = cookie; }
-    virtual Definition::Cookie *cookie() const { return m_cookie; }
     virtual void _setSymbolName(const QCString &name) { m_symbolName = name; }
     virtual QCString _symbolName() const { return m_symbolName; }
     DefinitionAliasImpl m_impl;
     const Definition *m_scope;
     const Definition *m_alias;
-    mutable Definition::Cookie *m_cookie;
     QCString m_symbolName;
 };
 
index 0f20636..af910f4 100644 (file)
@@ -255,7 +255,7 @@ static void writeMapArea(TextStream &t,const ClassDef *cd,QCString relPath,
     }
     t << "href=\"";
     t << externalRef(relPath,ref,TRUE);
-    t << cd->getOutputFileBase() << Doxygen::htmlFileExtension;
+    t << addHtmlExtensionIfMissing(cd->getOutputFileBase());
     if (!cd->anchor().isEmpty())
     {
       t << "#" << cd->anchor();
@@ -1071,7 +1071,6 @@ void ClassDiagram::writeFigure(TextStream &output,const QCString &path,
   if (realWidth>pageWidth) // assume that the page width is about 15 cm
   {
     realHeight*=pageWidth/realWidth;
-    realWidth=pageWidth;
   }
 
   //output << "}\n";
index 6920c0d..086b41a 100644 (file)
@@ -47,12 +47,12 @@ class DirDefImpl : public DefinitionMixin<DirDef>
     virtual bool isLinkableInProject() const;
     virtual bool isLinkable() const;
     virtual QCString displayName(bool=TRUE) const { return m_dispName; }
-    virtual const QCString &shortName() const { return m_shortName; }
+    virtual const QCString shortName() const { return m_shortName; }
     virtual void addSubDir(DirDef *subdir);
     virtual const FileList &getFiles() const { return m_fileList; }
     virtual void addFile(const FileDef *fd);
     virtual const DirList &subDirs() const { return m_subdirs; }
-    virtual bool isCluster() const { return m_subdirs.size()>0; }
+    virtual bool hasSubdirs() const { return !m_subdirs.empty(); }
     virtual int level() const { return m_level; }
     virtual DirDef *parent() const { return m_parent; }
     virtual int dirCount() const { return m_dirCount; }
@@ -66,9 +66,10 @@ class DirDefImpl : public DefinitionMixin<DirDef>
     virtual void setDiskName(const QCString &name) { m_diskName = name; }
     virtual void sort();
     virtual void setParent(DirDef *parent);
+    virtual void setDirCount(int count);
     virtual void setLevel();
     virtual void addUsesDependency(const DirDef *usedDir,const FileDef *srcFd,
-                                   const FileDef *dstFd,bool inherited);
+                                   const FileDef *dstFd,bool srcDirect, bool dstDirect);
     virtual void computeDependencies();
 
   public:
@@ -92,7 +93,7 @@ class DirDefImpl : public DefinitionMixin<DirDef>
     QCString m_shortName;
     QCString m_diskName;
     FileList m_fileList;                 // list of files in the group
-    int m_dirCount;
+    int m_dirCount = -1;
     int m_level;
     DirDef *m_parent;
     UsedDirLinkedMap m_usedDirs;
@@ -107,8 +108,6 @@ DirDef *createDirDef(const QCString &path)
 //----------------------------------------------------------------------
 // method implementation
 
-static int g_dirCount=0;
-
 DirDefImpl::DirDefImpl(const QCString &path) : DefinitionMixin(path,1,1,path)
 {
   bool fullPathNames = Config_getBool(FULL_PATH_NAMES);
@@ -132,7 +131,6 @@ DirDefImpl::DirDefImpl(const QCString &path) : DefinitionMixin(path,1,1,path)
     m_dispName = m_dispName.left(m_dispName.length()-1);
   }
 
-  m_dirCount   = g_dirCount++;
   m_level=-1;
   m_parent=0;
 }
@@ -163,6 +161,11 @@ void DirDefImpl::setParent(DirDef *p)
    m_parent=p;
 }
 
+void DirDefImpl::setDirCount(int count)
+{
+  m_dirCount=count;
+}
+
 void DirDefImpl::addFile(const FileDef *fd)
 {
   m_fileList.push_back(fd);
@@ -339,7 +342,7 @@ void DirDefImpl::writeSubDirList(OutputList &ol)
     ol.startMemberList();
     for(const auto dd : m_subdirs)
     {
-      if (dd->hasDocumentation() || dd->getFiles().empty())
+      if (dd->hasDocumentation() || !dd->getFiles().empty())
       {
         ol.startMemberDeclaration();
         ol.startMemberItem(dd->anchor(),0);
@@ -373,7 +376,12 @@ void DirDefImpl::writeFileList(OutputList &ol)
   int numFiles = 0;
   for (const auto &fd : m_fileList)
   {
-    if (fd->hasDocumentation())
+    bool genSourceFile;
+    if (fileVisibleInIndex(fd,genSourceFile))
+    {
+      numFiles++;
+    }
+    else if (genSourceFile)
     {
       numFiles++;
     }
@@ -388,7 +396,9 @@ void DirDefImpl::writeFileList(OutputList &ol)
     ol.startMemberList();
     for (const auto &fd : m_fileList)
     {
-      if (fd->hasDocumentation())
+      bool doc,src;
+      doc = fileVisibleInIndex(fd,src);
+      if (doc || src)
       {
         ol.startMemberDeclaration();
         ol.startMemberItem(fd->anchor(),0);
@@ -463,7 +473,7 @@ void DirDefImpl::writeTagFile(TextStream &tagFile)
   tagFile << "  <compound kind=\"dir\">\n";
   tagFile << "    <name>" << convertToXML(displayName()) << "</name>\n";
   tagFile << "    <path>" << convertToXML(name()) << "</path>\n";
-  tagFile << "    <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>\n";
+  tagFile << "    <filename>" << addHtmlExtensionIfMissing(getOutputFileBase()) << "</filename>\n";
   for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Directory))
   {
     switch (lde->kind())
@@ -629,9 +639,11 @@ void DirDefImpl::setLevel()
 
 /** Add as "uses" dependency between \a this dir and \a dir,
  *  that was caused by a dependency on file \a fd.
+ *  srcDirect and dstDirect indicate if it is a direct dependencies (true) or if
+ *  the dependencies was indirect (e.g. a parent dir that has a child dir that has the dependencies)
  */
 void DirDefImpl::addUsesDependency(const DirDef *dir,const FileDef *srcFd,
-                                   const FileDef *dstFd,bool inherited)
+                                   const FileDef *dstFd,bool srcDirect, bool dstDirect)
 {
   if (this==dir) return; // do not add self-dependencies
   //static int count=0;
@@ -650,7 +662,7 @@ void DirDefImpl::addUsesDependency(const DirDef *dir,const FileDef *srcFd,
      if (usedPair==0) // new file dependency
      {
        //printf("  => new file\n");
-       usedDir->addFileDep(srcFd,dstFd);
+       usedDir->addFileDep(srcFd,dstFd, srcDirect, dstDirect);
        added=TRUE;
      }
      else
@@ -661,8 +673,8 @@ void DirDefImpl::addUsesDependency(const DirDef *dir,const FileDef *srcFd,
   else // new directory dependency
   {
     //printf("  => new file\n");
-    auto newUsedDir = std::make_unique<UsedDir>(dir,inherited);
-    newUsedDir->addFileDep(srcFd,dstFd);
+    auto newUsedDir = std::make_unique<UsedDir>(dir);
+    newUsedDir->addFileDep(srcFd,dstFd, srcDirect, dstDirect);
     usedDir = m_usedDirs.add(dir->getOutputFileBase(),std::move(newUsedDir));
     added=TRUE;
   }
@@ -671,12 +683,20 @@ void DirDefImpl::addUsesDependency(const DirDef *dir,const FileDef *srcFd,
     if (dir->parent())
     {
       // add relation to parent of used dir
-      addUsesDependency(dir->parent(),srcFd,dstFd,inherited);
+      addUsesDependency(dir->parent(),
+                        srcFd,
+                        dstFd,
+                        srcDirect,
+                        false); // indirect dependency on dest dir
     }
     if (parent())
     {
       // add relation for the parent of this dir as well
-      parent()->addUsesDependency(dir,srcFd,dstFd,TRUE);
+      parent()->addUsesDependency(dir,
+                                 srcFd,
+                                 dstFd,
+                                 false, // indirect dependency from source dir
+                                 dstDirect);
     }
   }
 }
@@ -701,7 +721,7 @@ void DirDefImpl::computeDependencies()
           // add dependency: thisDir->usedDir
           //static int count=0;
           //printf("      %d: add dependency %s->%s\n",count++,qPrint(name()),qPrint(usedDir->name()));
-          addUsesDependency(usedDir,fd,ii.fileDef,FALSE);
+          addUsesDependency(usedDir,fd,ii.fileDef,true,true);
         }
       }
     }
@@ -729,14 +749,14 @@ bool DirDefImpl::isParentOf(const DirDef *dir) const
 
 bool DirDefImpl::depGraphIsTrivial() const
 {
-  return m_usedDirs.empty();
+  return m_usedDirs.empty() && m_parent==nullptr;
 }
 
 
 //----------------------------------------------------------------------
 
-UsedDir::UsedDir(const DirDef *dir,bool inherited) :
-   m_dir(dir), m_inherited(inherited)
+UsedDir::UsedDir(const DirDef *dir) :
+   m_dir(dir)
 {
 }
 
@@ -744,9 +764,12 @@ UsedDir::~UsedDir()
 {
 }
 
-void UsedDir::addFileDep(const FileDef *srcFd,const FileDef *dstFd)
+void UsedDir::addFileDep(const FileDef *srcFd,const FileDef *dstFd, bool srcDirect, bool dstDirect)
 {
   m_filePairs.add(FilePair::key(srcFd,dstFd),std::make_unique<FilePair>(srcFd,dstFd));
+  m_hasDirectDeps    = m_hasDirectDeps    || (srcDirect && dstDirect);
+  m_hasDirectSrcDeps = m_hasDirectSrcDeps || srcDirect;
+  m_hasDirectDstDeps = m_hasDirectDstDeps || dstDirect;
 }
 
 void UsedDir::sort()
@@ -993,7 +1016,6 @@ void buildDirectories()
   {
     for (const auto &fd : *fn)
     {
-      //printf("buildDirectories %s\n",qPrint(fd->name()));
       if (fd->getReference().isEmpty())
       {
         DirDef *dir;
@@ -1038,7 +1060,24 @@ void buildDirectories()
   std::sort(Doxygen::dirLinkedMap->begin(),
             Doxygen::dirLinkedMap->end(),
             [](const auto &d1,const auto &d2)
-            { return qstricmp(d1->shortName(),d2->shortName()) < 0; });
+            {
+              QCString s1 = d1->shortName(), s2 = d2->shortName();
+              int i = qstricmp(s1,s2);
+              if (i==0) // if sort name are equal, sort on full path
+              {
+                QCString n1 = d1->name(), n2 = d2->name();
+                int n = qstricmp(n1,n2);
+                return n < 0;
+              }
+              return i < 0;
+            });
+
+  // set the directory count identifier
+  int dirCount=0;
+  for (const auto &dir : *Doxygen::dirLinkedMap)
+  {
+    dir->setDirCount(dirCount++);
+  }
 
   computeCommonDirPrefix();
 }
@@ -1050,13 +1089,13 @@ void computeDirDependencies()
   {
     dir->setLevel();
   }
+
   // compute uses dependencies between directories
   for (const auto &dir : *Doxygen::dirLinkedMap)
   {
     //printf("computeDependencies for %s: #dirs=%d\n",qPrint(dir->name()),Doxygen::directories.count());
     dir->computeDependencies();
   }
-
 }
 
 void generateDirDocs(OutputList &ol)
index 3d775d0..2dff286 100644 (file)
@@ -63,19 +63,45 @@ class FilePairLinkedMap : public LinkedMap<FilePair>
 class UsedDir
 {
   public:
-    UsedDir(const DirDef *dir,bool inherited);
+    UsedDir(const DirDef *dir);
     virtual ~UsedDir();
-    void addFileDep(const FileDef *srcFd,const FileDef *dstFd);
+
+    /**
+     * Take up dependency between files.
+     * @param[in] srcFd dependent file which depends on dstFd
+     * @param[in] dstFd dependee file on which srcFd depends on
+     * @param[in] srcDirect true iff the source dependency was the direct (not inherited from a sub dir)
+     * @param[in] dstDirect true iff the destination dependency was direct (not inherited from a sub dir)
+     */
+    void addFileDep(const FileDef *srcFd,const FileDef *dstFd, bool srcDirect, bool dstDirect);
     FilePair *findFilePair(const QCString &name);
     const FilePairLinkedMap &filePairs() const { return m_filePairs; }
     const DirDef *dir() const { return m_dir; }
-    bool inherited() const { return m_inherited; }
+
+    /** Returns true iff any of the dependencies between source and destination files are
+     *  direct (i.e. not "inherited" from sub directories)
+     */
+    bool hasDirectDeps() const { return m_hasDirectDeps; }
+
+    /** Returns true iff any of the dependencies from the source file to the destination file are
+     *  directly coming from a file in the source directory (i.e. not inherited via sub directories)
+     */
+    bool hasDirectSrcDeps() const { return m_hasDirectSrcDeps; }
+
+    /** Returns true iff any of the dependencies from the source file to the destination file are
+     *  directly targeting a file in the destination directory (i.e. not inherited via sub directories)
+     */
+    bool hasDirectDstDeps() const { return m_hasDirectDstDeps; }
+
     void sort();
 
   private:
     const DirDef *m_dir;
     FilePairLinkedMap m_filePairs;
-    bool m_inherited;
+
+    bool m_hasDirectDeps    = false;
+    bool m_hasDirectSrcDeps = false;
+    bool m_hasDirectDstDeps = false;
 };
 
 // ------------------
@@ -95,12 +121,12 @@ class DirDef : public DefinitionMutable, public Definition
     virtual bool isLinkableInProject() const = 0;
     virtual bool isLinkable() const = 0;
     virtual QCString displayName(bool=TRUE) const = 0;
-    virtual const QCString &shortName() const = 0;
+    virtual const QCString shortName() const = 0;
     virtual void addSubDir(DirDef *subdir) = 0;
     virtual const FileList &getFiles() const = 0;
     virtual void addFile(const FileDef *fd) = 0;
     virtual const DirList &subDirs() const = 0;
-    virtual bool isCluster() const = 0;
+    virtual bool hasSubdirs() const = 0;
     virtual int level() const = 0;
     virtual DirDef *parent() const = 0;
     virtual int dirCount() const = 0;
@@ -115,11 +141,12 @@ class DirDef : public DefinitionMutable, public Definition
     virtual void writeTagFile(TextStream &t) = 0;
 
     virtual void setDiskName(const QCString &name) = 0;
+    virtual void setDirCount(int count) = 0;
     virtual void sort() = 0;
     virtual void setParent(DirDef *parent) = 0;
     virtual void setLevel() = 0;
     virtual void addUsesDependency(const DirDef *usedDir,const FileDef *srcFd,
-                                   const FileDef *dstFd,bool inherited) = 0;
+                                   const FileDef *dstFd,bool srcDirect, bool dstDirect) = 0;
     virtual void computeDependencies() = 0;
 };
 
index 041ab4b..ff85689 100644 (file)
@@ -168,9 +168,10 @@ void DocbookCodeGenerator::writeCodeLink(CodeSymbolType,
 void DocbookCodeGenerator::writeCodeLinkLine(CodeSymbolType,
     const QCString &,const QCString &file,
     const QCString &,const QCString &name,
-    const QCString &)
+    const QCString &,bool writeLineAnchor)
 {
   Docbook_DB(("(writeCodeLinkLine)\n"));
+  if (!writeLineAnchor) return;
   m_t << "<anchor xml:id=\"_" << stripExtensionGeneral(stripPath(file),".xml");
   m_t << "_1l";
   writeDocbookString(m_t,name);
@@ -222,7 +223,7 @@ void DocbookCodeGenerator::writeCodeAnchor(const QCString &)
 }
 
 void DocbookCodeGenerator::writeLineNumber(const QCString &ref,const QCString &fileName,
-    const QCString &anchor,int l)
+    const QCString &anchor,int l,bool writeLineAnchor)
 {
   Docbook_DB(("(writeLineNumber)\n"));
   m_insideCodeLine = TRUE;
@@ -233,7 +234,7 @@ void DocbookCodeGenerator::writeLineNumber(const QCString &ref,const QCString &f
 
     if (!m_sourceFileName.isEmpty())
     {
-      writeCodeLinkLine(CodeSymbolType::Default,ref,m_sourceFileName,anchor,lineNumber,QCString());
+      writeCodeLinkLine(CodeSymbolType::Default,ref,m_sourceFileName,anchor,lineNumber,QCString(),writeLineAnchor);
     }
     if (!fileName.isEmpty())
     {
index 5ed6fa5..ea4efe9 100644 (file)
@@ -37,7 +37,7 @@ class DocbookCodeGenerator : public CodeOutputInterface
     void writeCodeLinkLine(CodeSymbolType type,
         const QCString &ref,const QCString &file,
         const QCString &anchor,const QCString &name,
-        const QCString &tooltip);
+        const QCString &tooltip, bool);
     void writeTooltip(const QCString &, const DocLinkInfo &, const QCString &,
                       const QCString &, const SourceLinkInfo &, const SourceLinkInfo &
                      );
@@ -47,7 +47,7 @@ class DocbookCodeGenerator : public CodeOutputInterface
     void endFontClass();
     void writeCodeAnchor(const QCString &);
     void writeLineNumber(const QCString &extRef,const QCString &compId,
-        const QCString &anchorId,int l);
+        const QCString &anchorId,int l, bool writeLineAnchor);
     void setCurrentDoc(const Definition *,const QCString &,bool);
     void addWord(const QCString &,bool);
     void finish();
@@ -112,8 +112,8 @@ class DocbookGenerator : public OutputGenerator
                        const QCString &anchor,const QCString &name,
                        const QCString &tooltip)
     { m_codeGen.writeCodeLink(type,ref,file,anchor,name,tooltip); }
-    void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor,int lineNumber)
-    { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber); }
+    void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor,int lineNumber, bool writeLineAnchor)
+    { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber,writeLineAnchor); }
     void writeTooltip(const QCString &id, const DocLinkInfo &docInfo, const QCString &decl,
                       const QCString &desc, const SourceLinkInfo &defInfo, const SourceLinkInfo &declInfo
                      )
index 25fc21e..471bd3e 100644 (file)
@@ -295,6 +295,7 @@ DB_VIS_C
       /* There is no equivalent Docbook tag for rendering Small text */
     case DocStyleChange::Small: /* XSLT Stylesheets can be used */ break;
                                                                    /* HTML only */
+    case DocStyleChange::Cite:  break;
     case DocStyleChange::S:  break;
     case DocStyleChange::Strike:  break;
     case DocStyleChange::Del:        break;
@@ -302,6 +303,21 @@ DB_VIS_C
     case DocStyleChange::Ins:        break;
     case DocStyleChange::Div:  /* HTML only */ break;
     case DocStyleChange::Span: /* HTML only */ break;
+    case DocStyleChange::Details: /* emulation of the <details> tag */
+      if (s->enable())
+      {
+        m_t << "\n";
+        m_t << "<para>";
+      }
+      else
+      {
+        m_t << "</para>";
+        m_t << "\n";
+      }
+      break;
+    case DocStyleChange::Summary: /* emulation of the <summary> tag inside a <details> tag */
+      if (s->enable()) m_t << "<emphasis role=\"bold\">";      else m_t << "</emphasis>";
+      break;
   }
 }
 
@@ -331,6 +347,14 @@ DB_VIS_C
       filter(s->text());
       m_t << "</computeroutput></literallayout>";
       break;
+    case DocVerbatim::JavaDocLiteral:
+      filter(s->text(), true);
+      break;
+    case DocVerbatim::JavaDocCode:
+      m_t << "<computeroutput>";
+      filter(s->text(), true);
+      m_t << "</computeroutput>";
+      break;
     case DocVerbatim::HtmlOnly:
       break;
     case DocVerbatim::RtfOnly:
@@ -936,33 +960,7 @@ void DocbookDocVisitor::visitPre(DocHtmlList *s)
 {
 DB_VIS_C
   if (m_hide) return;
-  if (s->type()==DocHtmlList::Ordered)
-  {
-    m_t << "<orderedlist";
-    for (const auto &opt : s->attribs())
-    {
-      if (opt.name=="type")
-      {
-        if (opt.value=="1")
-          m_t << " numeration=\"arabic\"";
-        else if (opt.value=="a")
-          m_t << " numeration=\"loweralpha\"";
-        else if (opt.value=="A")
-          m_t << " numeration=\"upperalpha\"";
-        else if (opt.value=="i")
-          m_t << " numeration=\"lowerroman\"";
-        else if (opt.value=="I")
-          m_t << " numeration=\"upperroman\"";
-      }
-      else if (opt.name=="start")
-      {
-        m_t << " startingnumber=\"" << opt.value << "\"";
-      }
-    }
-    m_t << ">\n";
-  }
-  else
-    m_t << "<itemizedlist>\n";
+  // This will be handled in DocHtmlListItem
 }
 
 void DocbookDocVisitor::visitPost(DocHtmlList *s)
@@ -975,10 +973,68 @@ DB_VIS_C
     m_t << "</itemizedlist>\n";
 }
 
-void DocbookDocVisitor::visitPre(DocHtmlListItem *)
+void DocbookDocVisitor::visitPre(DocHtmlListItem *s)
 {
 DB_VIS_C
   if (m_hide) return;
+  DocHtmlList *l = (DocHtmlList *)s->parent();
+  if (l->type()==DocHtmlList::Ordered)
+  {
+    bool isFirst = l->children().front().get()==s;
+    int value = 0;
+    QCString type;
+    for (const auto &opt : s->attribs())
+    {
+      if (opt.name=="value")
+      {
+        bool ok;
+        int val = opt.value.toInt(&ok);
+        if (ok) value = val;
+      }
+    }
+
+    if (value>0 || isFirst)
+    {
+      for (const auto &opt : l->attribs())
+      {
+        if (opt.name=="type")
+        {
+          if (opt.value=="1")
+            type = " numeration=\"arabic\"";
+          else if (opt.value=="a")
+            type = " numeration=\"loweralpha\"";
+            else if (opt.value=="A")
+            type =  " numeration=\"upperalpha\"";
+          else if (opt.value=="i")
+            type =  " numeration=\"lowerroman\"";
+          else if (opt.value=="I")
+            type =  " numeration=\"upperroman\"";
+        }
+        else if (value==0 && opt.name=="start")
+        {
+          bool ok;
+          int val = opt.value.toInt(&ok);
+          if (ok) value = val;
+        }
+      }
+    }
+
+    if (value>0 && !isFirst)
+    {
+      m_t << "</orderedlist>\n";
+    }
+    if (value>0 || isFirst)
+    {
+      m_t << "<orderedlist";
+      if (!type.isEmpty()) m_t << type.data();
+      if (value>0)         m_t << " startingnumber=\"" << value << "\"";
+      m_t << ">\n";
+    }
+  }
+  else
+  {
+    m_t << "<itemizedlist>\n";
+  }
   m_t << "<listitem>\n";
 }
 
@@ -1043,6 +1099,15 @@ DB_VIS_C
     // do something with colwidth based of cell width specification (be aware of possible colspan in the header)?
     m_t << "      <colspec colname='c" << i+1 << "'/>\n";
   }
+  if (t->hasCaption())
+  {
+    DocHtmlCaption *c = t->caption();
+    m_t << "<caption>";
+    if (!c->file().isEmpty())
+    {
+      m_t << "<anchor xml:id=\"_" <<  stripPath(c->file()) << "_1" << filterId(c->anchor()) << "\"/>";
+    }
+  }
 }
 
 void DocbookDocVisitor::visitPost(DocHtmlTable *)
@@ -1162,7 +1227,7 @@ void DocbookDocVisitor::visitPre(DocHtmlCaption *)
 {
 DB_VIS_C
   if (m_hide) return;
-   m_t << "<caption>";
+  // start of caption is handled in the DocbookDocVisitor::visitPre(DocHtmlTable *t)
 }
 
 void DocbookDocVisitor::visitPost(DocHtmlCaption *)
@@ -1276,6 +1341,7 @@ void DocbookDocVisitor::visitPre(DocDotFile *df)
 {
 DB_VIS_C
   if (m_hide) return;
+  if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(DOCBOOK_OUTPUT)+"/"+stripPath(df->file()));
   startDotFile(df->file(),df->width(),df->height(),df->hasCaption(),df->children(),df->srcFile(),df->srcLine());
 }
 
@@ -1290,6 +1356,7 @@ void DocbookDocVisitor::visitPre(DocMscFile *df)
 {
 DB_VIS_C
   if (m_hide) return;
+  if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(DOCBOOK_OUTPUT)+"/"+stripPath(df->file()));
   startMscFile(df->file(),df->width(),df->height(),df->hasCaption(),df->children(),df->srcFile(),df->srcLine());
 }
 
@@ -1303,6 +1370,7 @@ void DocbookDocVisitor::visitPre(DocDiaFile *df)
 {
 DB_VIS_C
   if (m_hide) return;
+  if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(DOCBOOK_OUTPUT)+"/"+stripPath(df->file()));
   startDiaFile(df->file(),df->width(),df->height(),df->hasCaption(),df->children(),df->srcFile(),df->srcLine());
 }
 
@@ -1607,10 +1675,10 @@ DB_VIS_C
 }
 
 
-void DocbookDocVisitor::filter(const QCString &str)
+void DocbookDocVisitor::filter(const QCString &str, const bool retainNewLine)
 {
 DB_VIS_C
-  m_t << convertToDocBook(str);
+  m_t << convertToDocBook(str, retainNewLine);
 }
 
 void DocbookDocVisitor::startLink(const QCString &file,const QCString &anchor)
index 220dd5e..93ed94e 100644 (file)
@@ -139,7 +139,7 @@ class DocbookDocVisitor : public DocVisitor
     //--------------------------------------
     // helper functions
     //--------------------------------------
-    void filter(const QCString &str);
+    void filter(const QCString &str, const bool retainNewLine = false);
     void startLink(const QCString &file,
     const QCString &anchor);
     void endLink();
index 07ff8f3..875103c 100644 (file)
@@ -70,12 +70,12 @@ void DocGroup::enterCompound(const QCString &fileName,int line,const QCString &n
   {
     m_compoundName=fileName;
   }
-  //printf("groupEnterCompound(%s)\n",name);
+  //printf("groupEnterCompound(%s)\n",qPrint(name));
 }
 
-void DocGroup::leaveCompound(const QCString &,int,const QCString & /*name*/)
+void DocGroup::leaveCompound(const QCString &,int,const QCString & name)
 {
-  //printf("groupLeaveCompound(%s)\n",name);
+  //printf("groupLeaveCompound(%s)\n",qPrint(name));
   //if (m_memberGroupId!=DOX_NOGROUP)
   //{
   //  warn(fileName,line,"end of compound %s while inside a member group\n",qPrint(name));
@@ -106,7 +106,7 @@ int DocGroup::findExistingGroup(const MemberGroupInfo *info)
 void DocGroup::open(Entry *e,const QCString &,int, bool implicit)
 {
   if (!implicit) m_openCount++;
-  //printf("==> openGroup(name=%s,sec=%x) m_autoGroupStack=%d\n",
+  //printf("==> openGroup(name=%s,sec=%x) m_autoGroupStack=%zu\n",
   //   qPrint(e->name),e->section,m_autoGroupStack.size());
   if (e->section==Entry::GROUPDOC_SEC) // auto group
   {
@@ -146,8 +146,8 @@ void DocGroup::close(Entry *e,const QCString &fileName,int line,bool foundInline
       m_openCount--;
     }
   }
-  //printf("==> closeGroup(name=%s,sec=%x,file=%s,line=%d) m_autoGroupStack=%d\n",
-  //    qPrint(e->name),e->section,fileName,line,m_autoGroupStack.size());
+  //printf("==> closeGroup(name=%s,sec=%x,file=%s,line=%d) m_autoGroupStack=%zu\n",
+  //    qPrint(e->name),e->section,qPrint(fileName),line,m_autoGroupStack.size());
   if (m_memberGroupId!=DOX_NOGROUP) // end of member group
   {
     auto it = Doxygen::memberGroupInfoMap.find(m_memberGroupId);
@@ -177,15 +177,15 @@ void DocGroup::close(Entry *e,const QCString &fileName,int line,bool foundInline
 
 void DocGroup::initGroupInfo(Entry *e)
 {
-  //printf("==> initGroup(id=%d,related=%s,e=%p)\n",m_memberGroupId,
-  //       qPrint(m_memberGroupRelates),e);
+  //printf("==> initGroup(id=%d,related=%s,e=%p,#stack=%zu)\n",m_memberGroupId,
+  //       qPrint(m_memberGroupRelates),(void*)e,m_autoGroupStack.size());
   e->mGrpId     = m_memberGroupId;
   e->relates    = m_memberGroupRelates;
   if (!m_autoGroupStack.empty())
   {
-    //printf("Appending group %s to %s: count=%d entry=%p\n",
-    // qPrint(m_autoGroupStack.top()->groupname),
-    // qPrint(e->name),e->groups->count(),e);
+    //printf("Appending group %s to %s: count=%zu entry=%p\n",
+    // qPrint(m_autoGroupStack.back().groupname),
+    //    qPrint(e->name),e->groups.size(),(void*)e);
     e->groups.push_back(Grouping(m_autoGroupStack.back()));
   }
 }
index 2aa20cb..b8ffc23 100644 (file)
@@ -61,7 +61,7 @@
 //#define DBG(x) printf x
 
 // debug to stderr
-//#define myprintf(x...) fprintf(stderr,x)
+//#define myprintf(...) fprintf(stderr,__VA_ARGS__)
 //#define DBG(x) myprintf x
 
 #define INTERNAL_ASSERT(x) do {} while(0)
@@ -92,7 +92,24 @@ static const std::set<std::string> g_plantumlEngine {
 
 using DefinitionStack = std::vector<const Definition *>;
 using DocNodeStack = std::stack<const DocNode *>;
-using DocStyleChangeStack = std::stack<const DocStyleChange *>;
+//using DocStyleChangeStack = std::stack<const DocStyleChange *>;
+
+template<typename T, typename Container = std::deque<T>>
+class iterable_stack
+: public std::stack<T, Container>
+{
+    using std::stack<T, Container>::c;
+
+public:
+
+    // expose just the iterators of the underlying container
+    auto begin() { return std::begin(c); }
+    auto end() { return std::end(c); }
+
+    auto begin() const { return std::begin(c); }
+    auto end() const { return std::end(c); }
+};
+using DocStyleChangeStack = iterable_stack<const DocStyleChange *>;
 
 /** Parser's context to store all global variables.
  */
@@ -310,6 +327,10 @@ QCString DocParser::findAndCopyImage(const QCString &fileName, DocImage::Type ty
          if (!Config_getBool(GENERATE_RTF)) return result;
          outputDir = Config_getString(RTF_OUTPUT);
          break;
+        case DocImage::Xml:
+         if (!Config_getBool(GENERATE_XML)) return result;
+         outputDir = Config_getString(XML_OUTPUT);
+         break;
       }
       QCString outputFile = outputDir+"/"+result;
       FileInfo outfi(outputFile.str());
@@ -375,7 +396,7 @@ QCString DocParser::findAndCopyImage(const QCString &fileName, DocImage::Type ty
  */
 void DocParser::checkArgumentName()
 {
-  if (!Config_getBool(WARN_IF_DOC_ERROR)) return;
+  if (!(Config_getBool(WARN_IF_DOC_ERROR) || Config_getBool(WARN_IF_INCOMPLETE_DOC))) return;
   if (context.memberDef==0) return; // not a member
   std::string name = context.token->name.str();
   const ArgumentList &al=context.memberDef->isDocsForDefinition() ?
@@ -492,8 +513,8 @@ void DocParser::checkUnOrMultipleDocumentedParams()
           }
           else if (count>1 && Config_getBool(WARN_IF_DOC_ERROR))
           {
-            warn_doc_error(context.memberDef->getDefFileName(),
-                           context.memberDef->getDefLine(),
+            warn_doc_error(context.memberDef->docFile(),
+                           context.memberDef->docLine(),
                            "%s",
                            qPrint("argument '" + aName +
                            "' from the argument list of " +
@@ -520,8 +541,8 @@ void DocParser::checkUnOrMultipleDocumentedParams()
           first=FALSE;
           errMsg+="  parameter '"+argName+"'";
         }
-        warn_incomplete_doc(context.memberDef->getDefFileName(),
-                            context.memberDef->getDefLine(),
+        warn_incomplete_doc(context.memberDef->docFile(),
+                            context.memberDef->docLine(),
                             "%s",
                             qPrint(substitute(errMsg,"%","%%")));
       }
@@ -614,6 +635,15 @@ static bool insideTable(DocNode *n)
   return FALSE;
 }
 
+static const DocStyleChange *insideDetails(DocStyleChangeStack styleStack)
+{
+  const DocStyleChange *retItem = NULL;
+  for (auto i : styleStack)
+  {
+     if (i->style() == DocStyleChange::Details) retItem = i;
+  }
+  return retItem;
+}
 //---------------------------------------------------------------------------
 /*! Looks for a documentation block with name commandName in the current
  *  context (g_parserContext.context). The resulting documentation string is
@@ -830,6 +860,7 @@ int DocParser::handleStyleArgument(DocNode *parent,DocNodeList &children,const Q
           { // ignore </li> as the end of a style command
             continue;
           }
+          DBG(("handleStyleArgument(%s) end tok=%s\n",qPrint(saveCmdName), DocTokenizer::tokToString(tok)));
           return tok;
           break;
         default:
@@ -839,7 +870,7 @@ int DocParser::handleStyleArgument(DocNode *parent,DocNodeList &children,const Q
       break;
     }
   }
-  DBG(("handleStyleArgument(%s) end tok=%x\n",qPrint(saveCmdName),tok));
+  DBG(("handleStyleArgument(%s) end tok=%s\n",qPrint(saveCmdName), DocTokenizer::tokToString(tok)));
   return (tok==TK_NEWPARA || tok==TK_LISTITEM || tok==TK_ENDLIST
          ) ? tok : RetVal_OK;
 }
@@ -980,6 +1011,7 @@ const char *DocStyleChange::styleString() const
     case DocStyleChange::Code:         return "code";
     case DocStyleChange::Center:       return "center";
     case DocStyleChange::Small:        return "small";
+    case DocStyleChange::Cite:         return "cite";
     case DocStyleChange::Subscript:    return "subscript";
     case DocStyleChange::Superscript:  return "superscript";
     case DocStyleChange::Preformatted: return "pre";
@@ -990,6 +1022,8 @@ const char *DocStyleChange::styleString() const
     case DocStyleChange::Del:          return "del";
     case DocStyleChange::Underline:    return "u";
     case DocStyleChange::Ins:          return "ins";
+    case DocStyleChange::Details:      return "details";
+    case DocStyleChange::Summary:      return "summary";
   }
   return "<invalid>";
 }
@@ -1548,6 +1582,16 @@ reparsetoken:
               handleStyleLeave(parent,children,DocStyleChange::Ins,tokenName);
             }
             break;
+          case HTML_DETAILS:
+            if (!context.token->endTag)
+            {
+              handleStyleEnter(parent,children,DocStyleChange::Details,tokenName,&context.token->attribs);
+            }
+            else
+            {
+              handleStyleLeave(parent,children,DocStyleChange::Details,tokenName);
+            }
+            break;
           case HTML_CODE:
           case XML_C:
             if (!context.token->endTag)
@@ -1609,6 +1653,16 @@ reparsetoken:
               handleStyleLeave(parent,children,DocStyleChange::Small,tokenName);
             }
             break;
+          case HTML_CITE:
+            if (!context.token->endTag)
+            {
+              handleStyleEnter(parent,children,DocStyleChange::Cite,tokenName,&context.token->attribs);
+            }
+            else
+            {
+              handleStyleLeave(parent,children,DocStyleChange::Cite,tokenName);
+            }
+            break;
           case HTML_IMG:
             if (!context.token->endTag)
               handleImg(parent,children,context.token->attribs);
@@ -2982,7 +3036,6 @@ endheader:
   DBG(("DocHtmlHeader::parse() end\n"));
   return retval;
 }
-
 //---------------------------------------------------------------------------
 
 int DocHRef::parse()
@@ -3089,7 +3142,7 @@ int DocInternal::parse(int level)
     warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"\\internal command found inside internal section");
   }
 
-  DBG(("DocInternal::parse() end: retval=%x\n",retval));
+  DBG(("DocInternal::parse() end: retval=%s\n",DocTokenizer::retvalToString(retval)));
   return retval;
 }
 
@@ -3182,7 +3235,7 @@ int DocIndexEntry::parse()
   m_parser.tokenizer.setStatePara();
   m_entry = m_entry.stripWhiteSpace();
 endindexentry:
-  DBG(("DocIndexEntry::parse() end retval=%x\n",retval));
+  DBG(("DocIndexEntry::parse() end retval=%s\n",DocTokenizer::retvalToString(retval)));
   return retval;
 }
 
@@ -3281,7 +3334,7 @@ int DocHtmlCell::parse()
     if (retval==TK_HTMLTAG)
     {
       int tagId=Mappers::htmlTagMapper->map(m_parser.context.token->name);
-      if (tagId==HTML_TD && m_parser.context.token->endTag) // found </dt> tag
+      if (tagId==HTML_TD && m_parser.context.token->endTag) // found </td> tag
       {
         retval=TK_NEWPARA; // ignore the tag
       }
@@ -3291,7 +3344,7 @@ int DocHtmlCell::parse()
       }
     }
   }
-  while (retval==TK_NEWPARA);
+  while ((retval==TK_NEWPARA) || (retval==RetVal_EndParBlock));
   if (par) par->markLast();
 
   DBG(("DocHtmlCell::parse() end\n"));
@@ -4002,7 +4055,7 @@ int DocHtmlListItem::parse()
   while (retval==TK_NEWPARA);
   if (par) par->markLast();
 
-  DBG(("DocHtmlListItem::parse() end retval=%x\n",retval));
+  DBG(("DocHtmlListItem::parse() end retval=%s\n",DocTokenizer::retvalToString(retval)));
   return retval;
 }
 
@@ -4034,7 +4087,7 @@ int DocHtmlListItem::parseXml()
 
   if (par) par->markLast();
 
-  DBG(("DocHtmlListItem::parseXml() end retval=%x\n",retval));
+  DBG(("DocHtmlListItem::parseXml() end retval=%s\n",DocTokenizer::retvalToString(retval)));
   return retval;
 }
 
@@ -4111,7 +4164,7 @@ int DocHtmlList::parse()
   }
 
 endlist:
-  DBG(("DocHtmlList::parse() end retval=%x\n",retval));
+  DBG(("DocHtmlList::parse() end retval=%s\n",DocTokenizer::retvalToString(retval)));
   return retval==RetVal_EndList ? RetVal_OK : retval;
 }
 
@@ -4172,7 +4225,7 @@ int DocHtmlList::parseXml()
   }
 
 endlist:
-  DBG(("DocHtmlList::parseXml() end retval=%x\n",retval));
+  DBG(("DocHtmlList::parseXml() end retval=%s\n",DocTokenizer::retvalToString(retval)));
   return retval==RetVal_EndList ||
          (retval==RetVal_CloseXml || m_parser.context.token->name=="list") ?
          RetVal_OK : retval;
@@ -4199,7 +4252,7 @@ int DocHtmlBlockQuote::parse()
   while (retval==TK_NEWPARA);
   if (par) par->markLast();
 
-  DBG(("DocHtmlBlockQuote::parse() end retval=%x\n",retval));
+  DBG(("DocHtmlBlockQuote::parse() end retval=%s\n",DocTokenizer::retvalToString(retval)));
   return (retval==RetVal_EndBlockQuote) ? RetVal_OK : retval;
 }
 
@@ -4224,7 +4277,7 @@ int DocParBlock::parse()
   while (retval==TK_NEWPARA);
   if (par) par->markLast();
 
-  DBG(("DocParBlock::parse() end retval=%x\n",retval));
+  DBG(("DocParBlock::parse() end retval=%s\n",DocTokenizer::retvalToString(retval)));
   return (retval==RetVal_EndBlockQuote) ? RetVal_OK : retval;
 }
 
@@ -4578,8 +4631,8 @@ int DocParamList::parse(const QCString &cmdName)
   {
     if (tok!=TK_NEWPARA) /* empty param description */
     {
-      warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token in comment block while parsing the "
-          "argument of command %s",qPrint(saveCmdName));
+      warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"unexpected token %s in comment block while parsing the "
+          "argument of command %s",DocTokenizer::tokToString(tok),qPrint(saveCmdName));
     }
     retval=RetVal_EndParBlock;
     goto endparamlist;
@@ -4991,9 +5044,10 @@ void DocPara::handleImage(const QCString &cmdName)
   else if (imgType=="latex")   t=DocImage::Latex;
   else if (imgType=="docbook") t=DocImage::DocBook;
   else if (imgType=="rtf")     t=DocImage::Rtf;
+  else if (imgType=="xml")     t=DocImage::Xml;
   else
   {
-    warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"output format %s specified as the first argument of "
+    warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"output format `%s` specified as the first argument of "
         "%s command is not valid",
         qPrint(imgType),qPrint(saveCmdName));
     return;
@@ -5072,9 +5126,11 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink)
         DocTokenizer::tokToString(tok),qPrint(saveCmdName));
     return;
   }
+  if (saveCmdName == "javalink") m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Code,cmdName,TRUE));
   m_parser.tokenizer.setStatePara();
   DocLink *lnk = new DocLink(m_parser,this,m_parser.context.token->name);
   m_children.push_back(std::unique_ptr<DocLink>(lnk));
+  if (saveCmdName == "javalink") m_children.push_back(std::make_unique<DocStyleChange>(m_parser,this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Code,cmdName,FALSE));
   QCString leftOver = lnk->parse(isJavaLink);
   if (!leftOver.isEmpty())
   {
@@ -5570,6 +5626,53 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok)
         m_parser.tokenizer.setStatePara();
       }
       break;
+    case CMD_ILITERAL:
+      {
+        DocVerbatim::Type t = DocVerbatim::JavaDocLiteral;
+        m_parser.tokenizer.setStateILiteralOpt();
+        retval = m_parser.tokenizer.lex();
+
+        QCString fullMatch = m_parser.context.token->verb;
+        int idx = fullMatch.find('{');
+        int idxEnd = fullMatch.find("}",idx+1);
+        StringVector optList;
+        if (idx != -1) // options present
+        {
+           QCString optStr = fullMatch.mid(idx+1,idxEnd-idx-1).stripWhiteSpace();
+           optList = split(optStr.str(),",");
+           for (const auto &opt : optList)
+           {
+             if (opt.empty()) continue;
+             QCString locOpt(opt);
+             locOpt = locOpt.stripWhiteSpace().lower();
+             if (locOpt == "code")
+             {
+               t = DocVerbatim::JavaDocCode;
+             }
+             else if (!locOpt.isEmpty())
+             {
+               warn(m_parser.context.fileName,m_parser.tokenizer.getLineNr(), "Unknown option '%s' for '\\iliteral'",qPrint(opt));
+             }
+           }
+        }
+
+        m_parser.tokenizer.setStateILiteral();
+        retval = m_parser.tokenizer.lex();
+        m_children.push_back(std::make_unique<DocVerbatim>(m_parser,this,m_parser.context.context,m_parser.context.token->verb,t,m_parser.context.isExample,m_parser.context.exampleName));
+        if (retval==0)
+        {
+          if (t == DocVerbatim::JavaDocCode)
+          {
+            warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"javadoc code section ended without end marker");
+          }
+          else
+          {
+            warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),"javadoc literal section ended without end marker");
+          }
+        }
+        m_parser.tokenizer.setStatePara();
+      }
+      break;
     case CMD_VERBATIM:
       {
         m_parser.tokenizer.setStateVerbatim();
@@ -5729,6 +5832,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok)
     case CMD_ENDDBONLY:
     case CMD_ENDLINK:
     case CMD_ENDVERBATIM:
+    case CMD_ENDILITERAL:
     case CMD_ENDDOT:
     case CMD_ENDMSC:
     case CMD_ENDUML:
@@ -5936,7 +6040,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok)
          retval==RetVal_Internal || retval==RetVal_SwitchLang ||
          retval==RetVal_EndInternal
         );
-  DBG(("handleCommand(%s) end retval=%x\n",qPrint(cmdName),retval));
+  DBG(("handleCommand(%s) end retval=%s\n",qPrint(cmdName),DocTokenizer::retvalToString(retval)));
   return retval;
 }
 
@@ -5958,7 +6062,7 @@ static bool findAttribute(const HtmlAttribList &tagHtmlAttribs,
 
 int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &tagHtmlAttribs)
 {
-  DBG(("handleHtmlStartTag(%s,%d)\n",qPrint(tagName),tagHtmlAttribs.count()));
+  DBG(("handleHtmlStartTag(%s,%d)\n",qPrint(tagName),tagHtmlAttribs.size()));
   int retval=RetVal_OK;
   int tagId = Mappers::htmlTagMapper->map(tagName);
   if (m_parser.context.token->emptyTag && !(tagId&XML_CmdMask) &&
@@ -6014,6 +6118,9 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta
     case HTML_INS:
       if (!m_parser.context.token->emptyTag) m_parser.handleStyleEnter(this,m_children,DocStyleChange::Ins,tagName,&m_parser.context.token->attribs);
       break;
+    case HTML_DETAILS:
+      if (!m_parser.context.token->emptyTag) m_parser.handleStyleEnter(this,m_children,DocStyleChange::Details,tagName,&m_parser.context.token->attribs);
+      break;
     case HTML_CODE:
       if (m_parser.context.token->emptyTag) break;
       if (/*getLanguageFromFileName(m_parser.context.fileName)==SrcLangExt_CSharp ||*/ m_parser.context.xmlComment)
@@ -6049,6 +6156,9 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta
     case HTML_SMALL:
       if (!m_parser.context.token->emptyTag) m_parser.handleStyleEnter(this,m_children,DocStyleChange::Small,tagName,&m_parser.context.token->attribs);
       break;
+    case HTML_CITE:
+      if (!m_parser.context.token->emptyTag) m_parser.handleStyleEnter(this,m_children,DocStyleChange::Cite,tagName,&m_parser.context.token->attribs);
+      break;
     case HTML_PRE:
       if (m_parser.context.token->emptyTag) break;
       m_parser.handleStyleEnter(this,m_children,DocStyleChange::Preformatted,tagName,&m_parser.context.token->attribs);
@@ -6138,6 +6248,11 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta
       break;
 
     case XML_SUMMARY:
+      if (insideDetails(m_parser.context.styleStack))
+      {
+        if (!m_parser.context.token->emptyTag) m_parser.handleStyleEnter(this,m_children,DocStyleChange::Summary,tagName,&m_parser.context.token->attribs);
+        break;
+      }
     case XML_REMARKS:
     case XML_EXAMPLE:
       m_parser.context.xmlComment=TRUE;
@@ -6439,6 +6554,9 @@ int DocPara::handleHtmlEndTag(const QCString &tagName)
     case HTML_INS:
       m_parser.handleStyleLeave(this,m_children,DocStyleChange::Ins,tagName);
       break;
+    case HTML_DETAILS:
+      m_parser.handleStyleLeave(this,m_children,DocStyleChange::Details,tagName);
+      break;
     case HTML_CODE:
       m_parser.handleStyleLeave(this,m_children,DocStyleChange::Code,tagName);
       break;
@@ -6463,6 +6581,9 @@ int DocPara::handleHtmlEndTag(const QCString &tagName)
     case HTML_SMALL:
       m_parser.handleStyleLeave(this,m_children,DocStyleChange::Small,tagName);
       break;
+    case HTML_CITE:
+      m_parser.handleStyleLeave(this,m_children,DocStyleChange::Cite,tagName);
+      break;
     case HTML_PRE:
       m_parser.handleStyleLeave(this,m_children,DocStyleChange::Preformatted,tagName);
       setInsidePreformatted(FALSE);
@@ -6531,6 +6652,11 @@ int DocPara::handleHtmlEndTag(const QCString &tagName)
       //m_children.push_back(std::make_unique<DocStyleChange>(this,(uint)m_parser.context.nodeStack.size(),DocStyleChange::Bold,FALSE));
       break;
     case XML_SUMMARY:
+      if (insideDetails(m_parser.context.styleStack))
+      {
+        m_parser.handleStyleLeave(this,m_children,DocStyleChange::Summary,tagName);
+        break;
+      }
     case XML_REMARKS:
     case XML_PARA:
     case XML_VALUE:
@@ -6765,7 +6891,7 @@ reparsetoken:
 
           // handle the command
           retval=handleCommand(m_parser.context.token->name,tok);
-          DBG(("handleCommand returns %x\n",retval));
+          DBG(("handleCommand returns %s\n",DocTokenizer::retvalToString(retval)));
 
           // check the return value
           if (retval==RetVal_SimpleSec)
@@ -6872,14 +6998,14 @@ reparsetoken:
         break;
       default:
         warn_doc_error(m_parser.context.fileName,m_parser.tokenizer.getLineNr(),
-            "Found unexpected token (id=%x)\n",tok);
+            "Found unexpected token (id=%s)\n",DocTokenizer::tokToString(tok));
         break;
     }
   }
   retval=0;
 endparagraph:
   m_parser.handlePendingStyleCommands(this,m_children);
-  DBG(("DocPara::parse() end retval=%x\n",retval));
+  DBG(("DocPara::parse() end retval=%s\n",DocTokenizer::retvalToString(retval)));
   const DocNode *n = m_parser.context.nodeStack.top();
   if (!m_parser.context.token->endTag && n->kind()==DocNode::Kind_Para &&
       retval==TK_NEWPARA && m_parser.context.token->name.lower() == "p")
@@ -7013,7 +7139,7 @@ int DocSection::parse()
                   retval==RetVal_EndInternal
                  );
 
-  DBG(("DocSection::parse() end: retval=%x\n",retval));
+  DBG(("DocSection::parse() end: retval=%s\n",DocTokenizer::retvalToString(retval)));
   return retval;
 }
 
@@ -7337,6 +7463,7 @@ static QCString extractCopyDocId(const char *data, uint &j, uint len)
     j+=9;
   }
   e=j;
+  if (j>0 && data[j-1]=='.') { e--; } // do not include punctuation added by Definition::_setBriefDescription()
   QCString id(data+s,e-s);
   //printf("extractCopyDocId='%s' input='%s'\n",qPrint(id),&data[s]);
   return id;
@@ -7370,6 +7497,7 @@ static uint isVerbatimSection(const char *data,uint i,uint len,QCString &endMark
     CHECK_FOR_COMMAND("code",endMarker="endcode");
     CHECK_FOR_COMMAND("msc",endMarker="endmsc");
     CHECK_FOR_COMMAND("verbatim",endMarker="endverbatim");
+    CHECK_FOR_COMMAND("iliteral",endMarker="endiliteral");
     CHECK_FOR_COMMAND("latexonly",endMarker="endlatexonly");
     CHECK_FOR_COMMAND("htmlonly",endMarker="endhtmlonly");
     CHECK_FOR_COMMAND("xmlonly",endMarker="endxmlonly");
index 073a013..e60b1a1 100644 (file)
@@ -357,7 +357,10 @@ class DocStyleChange : public DocNode
                  Underline     = (1<<11),
                  Del           = (1<<12),
                  Ins           = (1<<13),
-                 S             = (1<<14)
+                 S             = (1<<14),
+                 Details       = (1<<15),
+                 Summary       = (1<<16),
+                 Cite          = (1<<17)
                };
 
     DocStyleChange(DocParser &parser,DocNode *parent,uint position,Style s,const QCString &tagName,bool enable,
@@ -510,7 +513,7 @@ class DocSeparator : public DocNode
 class DocVerbatim : public DocNode
 {
   public:
-    enum Type { Code, HtmlOnly, ManOnly, LatexOnly, RtfOnly, XmlOnly, Verbatim, Dot, Msc, DocbookOnly, PlantUML };
+    enum Type { Code, HtmlOnly, ManOnly, LatexOnly, RtfOnly, XmlOnly, Verbatim, Dot, Msc, DocbookOnly, PlantUML, JavaDocCode, JavaDocLiteral };
     DocVerbatim(DocParser &parser,DocNode *parent,const QCString &context,
                 const QCString &text, Type t,bool isExample,
                 const QCString &exampleFile,bool isBlock=FALSE,const QCString &lang=QCString());
@@ -771,7 +774,7 @@ class DocXRefItem : public CompAccept<DocXRefItem>
 class DocImage : public CompAccept<DocImage>
 {
   public:
-    enum Type { Html, Latex, Rtf, DocBook };
+    enum Type { Html, Latex, Rtf, DocBook, Xml };
     DocImage(DocParser &parser,DocNode *parent,const HtmlAttribList &attribs,
              const QCString &name,Type t,const QCString &url=QCString(), bool inlineImage = TRUE);
     Kind kind() const override           { return Kind_Image; }
index bf589c4..a18ac82 100644 (file)
@@ -58,6 +58,8 @@ void DocSets::initialize()
   if (bundleId.isEmpty()) bundleId="org.doxygen.Project";
   QCString feedName = Config_getString(DOCSET_FEEDNAME);
   if (feedName.isEmpty()) feedName="FeedName";
+  QCString feedURL = Config_getString(DOCSET_FEEDURL);
+  if (feedURL.isEmpty()) feedURL="FeedUrl";
   QCString publisherId = Config_getString(DOCSET_PUBLISHER_ID);
   if (publisherId.isEmpty()) publisherId="PublisherId";
   QCString publisherName = Config_getString(DOCSET_PUBLISHER_NAME);
@@ -136,6 +138,8 @@ void DocSets::initialize()
           "     <string>" << projectNumber << "</string>\n"
           "     <key>DocSetFeedName</key>\n"
           "     <string>" << feedName << "</string>\n"
+          "     <key>DocSetFeedUrl</key>\n"
+          "     <string>" << feedURL << "</string>\n"
           "     <key>DocSetPublisherIdentifier</key>\n"
           "     <string>" << publisherId << "</string>\n"
           "     <key>DocSetPublisherName</key>\n"
@@ -257,7 +261,7 @@ void DocSets::addContentsItem(bool isDir,
       }
       else if (!file.isEmpty()) // doxygen generated file
       {
-        p->nts << file << Doxygen::htmlFileExtension;
+        p->nts << addHtmlExtensionIfMissing(file);
       }
       p->nts << "</Path>\n";
       if (!file.isEmpty() && !anchor.isEmpty())
@@ -509,8 +513,7 @@ void DocSets::writeToken(TextStream &t,
     t << "      <Scope>" << convertToXML(scope) << "</Scope>\n";
   }
   t << "    </TokenIdentifier>\n";
-  t << "    <Path>" << d->getOutputFileBase()
-                    << Doxygen::htmlFileExtension << "</Path>\n";
+  t << "    <Path>" << addHtmlExtensionIfMissing(d->getOutputFileBase()) << "</Path>\n";
   if (!anchor.isEmpty())
   {
     t << "    <Anchor>" << anchor << "</Anchor>\n";
index f1b10eb..43e4092 100644 (file)
@@ -126,6 +126,7 @@ class DocTokenizer
 
     // helper functions
     static const char *tokToString(int token);
+    static const char *retvalToString(int retval);
 
     void setLineNr(int lineno);
     int getLineNr(void);
@@ -150,6 +151,8 @@ class DocTokenizer
     void setStateDbOnly();
     void setStateRtfOnly();
     void setStateVerbatim();
+    void setStateILiteral();
+    void setStateILiteralOpt();
     void setStateDot();
     void setStateMsc();
     void setStateParam();
index ed53565..f5ccc19 100644 (file)
 %option extra-type="struct doctokenizerYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -142,6 +146,32 @@ const char *DocTokenizer::tokToString(int token)
   return "ERROR";
 }
 
+const char *DocTokenizer::retvalToString(int retval)
+{
+  switch (retval)
+  {
+    case RetVal_OK:            return "RetVal_OK";
+    case RetVal_SimpleSec:     return "RetVal_SimpleSec";
+    case RetVal_ListItem:      return "RetVal_ListItem";
+    case RetVal_Section:       return "RetVal_Section";
+    case RetVal_Subsection:    return "RetVal_Subsection";
+    case RetVal_Subsubsection: return "RetVal_Subsubsection";
+    case RetVal_Paragraph:     return "RetVal_Paragraph";
+    case RetVal_SubParagraph:  return "RetVal_SubParagraph";
+    case RetVal_EndList:       return "RetVal_EndList";
+    case RetVal_EndPre:        return "RetVal_EndPre";
+    case RetVal_DescData:      return "RetVal_DescData";
+    case RetVal_DescTitle :    return "RetVal_DescTitle";
+    case RetVal_EndDesc:       return "RetVal_EndDesc";
+    case RetVal_TableRow:      return "RetVal_TableRow";
+    case RetVal_TableCell:     return "RetVal_TableCell";
+    case RetVal_TableHCell:    return "RetVal_TableHCell";
+    case RetVal_EndTable:      return "RetVal_EndTable";
+    case RetVal_Internal:      return "RetVal_Internal";
+  }
+  return "ERROR";
+}
+
 static int computeIndent(const char *str,size_t length)
 {
   if (str==0 || length==std::string::npos) return 0;
@@ -214,6 +244,10 @@ static QCString stripEmptyLines(const QCString &s)
 #undef  YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
+
 //--------------------------------------------------------------------------
 //#define REAL_YY_DECL int doctokenizerYYlex (void)
 //#define YY_DECL static int local_doctokenizer(void)
@@ -232,8 +266,8 @@ PHPTYPE   [\\:a-z_A-Z0-9\x80-\xFF\-]+
 CITESCHAR [a-z_A-Z0-9\x80-\xFF\-\?]
 CITEECHAR [a-z_A-Z0-9\x80-\xFF\-\+:\/\?]
 CITEID    {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*|"\""{CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*"\""
-MAILADDR  ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+
-MAILWS    [\t a-z_A-Z0-9+-]
+MAILADDR  ("mailto:")?[a-z_A-Z0-9\x80-\xFF.+-]+"@"[a-z_A-Z0-9\x80-\xFf-]+("."[a-z_A-Z0-9\x80-\xFf\-]+)+[a-z_A-Z0-9\x80-\xFf\-]+
+MAILWS    [\t a-z_A-Z0-9\x80-\xFF+-]
 MAILADDR2 {MAILWS}+{BLANK}+("at"|"AT"|"_at_"|"_AT_"){BLANK}+{MAILWS}+("dot"|"DOT"|"_dot_"|"_DOT_"){BLANK}+{MAILWS}+
 OPTSTARS  ("/""/"{BLANK}*)?"*"*{BLANK}*
 LISTITEM  {BLANK}*[-]("#")?{WS}
@@ -262,7 +296,7 @@ INOUT     "in"|"out"|("in"{BLANK}*","?{BLANK}*"out")|("out"{BLANK}*","?{BLANK}*"
 PARAMIO   {CMD}param{BLANK}*"["{BLANK}*{INOUT}{BLANK}*"]"
 VARARGS   "..."
 TEMPCHAR  [a-z_A-Z0-9.,: \t\*\&\(\)\[\]]
-FUNCCHAR  [a-z_A-Z0-9,:\<\> \t\^\*\&\[\]]|{VARARGS}
+FUNCCHAR  [a-z_A-Z0-9,:\<\> \t\n\^\*\&\[\]]|{VARARGS}|"\\ilinebr"
 FUNCPART  {FUNCCHAR}*("("{FUNCCHAR}*")"{FUNCCHAR}*)?
 SCOPESEP  "::"|"#"|"."
 TEMPLPART "<"{TEMPCHAR}*("<"{TEMPCHAR}*("<"{TEMPCHAR}*">")?">")?">"
@@ -288,7 +322,7 @@ LNKWORD3  ([0-9a-z_A-Z\-]+("/"|"\\"))*[0-9a-z_A-Z\-]+("."[0-9a-z_A-Z]+)+
 CHARWORDQ [^ \t\n\r\\@<>()\[\]:;\?{}&%$#,."=']
 ESCWORD   ("%"{ID}(("::"|"."){ID})*)|("%'")
 CHARWORDQ1 [^ \-+0-9\t\n\r\\@<>()\[\]:;\?{}&%$#,."=']
-WORD1     {ESCWORD}|{CHARWORDQ1}{CHARWORDQ}*|"{"|"}"|"'\"'"|("\""([^"\n]*\n?)*[^"\n]*"\"")
+WORD1     {ESCWORD}|{CHARWORDQ1}{CHARWORDQ}*|"{"|"}"|"'\"'"|("\""([^"\n]*(\\\"|\n)?)*[^"\n]*"\"")
 WORD2     "."|","|"("|")"|"["|"]"|"::"|":"|";"|"\?"|"="|"'"
 WORD1NQ   {ESCWORD}|{CHARWORDQ}+|"{"|"}"
 WORD2NQ   "."|","|"("|")"|"["|"]"|"::"|":"|";"|"\?"|"="|"'"
@@ -328,6 +362,8 @@ LINENR {BLANK}*[1-9][0-9]*
 %x St_XmlOnly
 %x St_DbOnly
 %x St_Verbatim
+%x St_ILiteral
+%x St_ILiteralOpt
 %x St_Dot
 %x St_Msc
 %x St_PlantUMLOpt
@@ -485,6 +521,10 @@ LINENR {BLANK}*[1-9][0-9]*
                          yyextra->token->indent = computeIndent(text.data(),dotPos);
                          return TK_ENDLIST;
                        }
+<St_Para>"{"{BLANK}*"@linkplain"/{WS}+ {
+                         yyextra->token->name = "javalinkplain";
+                         return TK_COMMAND_AT;
+                       }
 <St_Para>"{"{BLANK}*"@link"/{WS}+ {
                          yyextra->token->name = "javalink";
                          return TK_COMMAND_AT;
@@ -622,6 +662,10 @@ LINENR {BLANK}*[1-9][0-9]*
                          yyextra->token->name = yytext;
                          return TK_LNKWORD;
                         }
+<St_Para>{LNKWORD1}/"<tt>" { // prevent <tt> html tag to be parsed as template arguments
+                         yyextra->token->name = yytext;
+                         return TK_LNKWORD;
+                       }
 <St_Para>{LNKWORD1}/"<br>"           | // prevent <br> html tag to be parsed as template arguments
 <St_Para>{LNKWORD1}                  |
 <St_Para>{LNKWORD1}{FUNCARG}         |
@@ -811,12 +855,28 @@ LINENR {BLANK}*[1-9][0-9]*
                          yyextra->token->verb=stripEmptyLines(yyextra->token->verb);
                          return RetVal_OK;
                        }
-<St_Verbatim>[^\\@\n]+ |
-<St_Verbatim>\n        |
-<St_Verbatim>.         { /* Verbatim text */
+<St_ILiteral>{CMD}"endiliteral " { // note extra space as this is artificially added
+                         // remove spaces that have been added
+                         yyextra->token->verb=yyextra->token->verb.mid(1,yyextra->token->verb.length()-2);
+                         return RetVal_OK;
+                       }
+<St_Verbatim,St_ILiteral>[^\\@\n]+ |
+<St_Verbatim,St_ILiteral>\n        |
+<St_Verbatim,St_ILiteral>.         { /* Verbatim / javadac literal/code text */
                          lineCount(yytext,yyleng);
                          yyextra->token->verb+=yytext;
                        }
+<St_ILiteralOpt>{BLANK}*"{"[a-zA-Z_,:0-9\. ]*"}" { // option(s) present
+                         yyextra->token->verb = QCString(yytext).stripWhiteSpace();
+                         return RetVal_OK;
+                       }
+<St_ILiteralOpt>"\\ilinebr" |
+<St_ILiteralOpt>"\n"   |
+<St_ILiteralOpt>.      {
+                         yyextra->token->sectionId = "";
+                         unput_string(yytext,yyleng);
+                         return RetVal_OK;
+                       }
 <St_Dot>{CMD}"enddot"  {
                          return RetVal_OK;
                        }
@@ -1282,6 +1342,10 @@ LINENR {BLANK}*[1-9][0-9]*
                                       yyextra->endMarker="endverbatim";
                                       BEGIN(St_SecSkip);
                                     }
+<St_Sections>{CMD}"iliteral"/[^a-z_A-Z0-9]  {
+                                      yyextra->endMarker="endiliteral";
+                                      BEGIN(St_SecSkip);
+                                    }
 <St_Sections>{CMD}"dot"/[^a-z_A-Z0-9] {
                                       yyextra->endMarker="enddot";
                                       BEGIN(St_SecSkip);
@@ -1732,6 +1796,22 @@ void DocTokenizer::setStateLatexOnly()
   BEGIN(St_LatexOnly);
 }
 
+void DocTokenizer::setStateILiteral()
+{
+  yyscan_t yyscanner = p->yyscanner;
+  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+  yyextra->token->verb="";
+  BEGIN(St_ILiteral);
+}
+
+void DocTokenizer::setStateILiteralOpt()
+{
+  yyscan_t yyscanner = p->yyscanner;
+  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+  yyextra->token->verb="";
+  BEGIN(St_ILiteralOpt);
+}
+
 void DocTokenizer::setStateVerbatim()
 {
   yyscan_t yyscanner = p->yyscanner;
index 5d6aa27..e42b73d 100644 (file)
@@ -146,7 +146,7 @@ DotFilePatcher *DotManager::createFilePatcher(const QCString &fileName)
 
   if (patcher != m_filePatchers.end()) return &(patcher->second);
 
-  auto rv = m_filePatchers.emplace(fileName.str(), fileName.data());
+  auto rv = m_filePatchers.emplace(std::make_pair(fileName.str(), fileName));
   assert(rv.second);
   return &(rv.first->second);
 }
@@ -287,7 +287,7 @@ void writeDotGraphFromFile(const QCString &inFile,const QCString &outDir,
   DotRunner dotRun(inFile);
   if (format==GOF_BITMAP)
   {
-    dotRun.addJob(Config_getEnum(DOT_IMAGE_FORMAT),absImgName,srcFile,srcLine);
+    dotRun.addJob(Config_getEnumAsString(DOT_IMAGE_FORMAT),absImgName,srcFile,srcLine);
   }
   else // format==GOF_EPS
   {
index 53edf87..382f4eb 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef DOTCALLGRAPH_H
 #define DOTCALLGRAPH_H
 
+#include <memory>
+
 #include "dotnode.h"
 #include "dotgraph.h"
 #include "memberdef.h"
@@ -51,4 +53,6 @@ class DotCallGraph : public DotGraph
     const Definition * m_scope;
 };
 
+using DotCallGraphPtr = std::shared_ptr<DotCallGraph>;
+
 #endif
index 6ccba08..d4ffb14 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef DOTCLASSGRAPH_H
 #define DOTCLASSGRAPH_H
 
+#include <memory>
+
 #include "classdef.h"
 #include "dotnode.h"
 #include "dotgraph.h"
@@ -61,5 +63,6 @@ private:
   bool               m_lrRank;
 };
 
+using DotClassGraphPtr = std::shared_ptr<DotClassGraph>;
 
 #endif
index 12236a0..27ba67c 100644 (file)
 *
 */
 
-#include <sstream>
-
 #include "dotdirdeps.h"
 #include "util.h"
 #include "doxygen.h"
 #include "config.h"
+#include "image.h"
+
+#include <algorithm>
+#include <iterator>
+#include <utility>
+#include <cstdint>
+#include <math.h>
+#include <cassert>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
 
 using DirDefMap = std::map<std::string,const DirDef *>;
 
+/** Properties are used to format the directories in the graph distinctively. */
+struct DotDirProperty
+{
+  bool isIncomplete = false; //!< true if not all successors of a cluster are drawn
+  bool isOrphaned   = false; //!< true if parent is not drawn
+  bool isTruncated  = false; //!< true has successors, none is drawn
+  bool isOriginal   = false; //!< true if is the directory for which the graph is drawn
+  bool isPeripheral = false; //!< true if no successor of parent of original directory
+};
+
+/** Builder helper to create instances of the DotDirProperty struct */
+class DotDirPropertyBuilder
+{
+  public:
+    DotDirPropertyBuilder &makeIncomplete(bool b=true) { m_property.isIncomplete=b; return *this; }
+    DotDirPropertyBuilder &makeOrphaned  (bool b=true) { m_property.isOrphaned  =b; return *this; }
+    DotDirPropertyBuilder &makeTruncated (bool b=true) { m_property.isTruncated =b; return *this; }
+    DotDirPropertyBuilder &makeOriginal  (bool b=true) { m_property.isOriginal  =b; return *this; }
+    DotDirPropertyBuilder &makePeripheral(bool b=true) { m_property.isPeripheral=b; return *this; }
+    operator DotDirProperty() { return std::move(m_property); }
+  private:
+    DotDirProperty m_property;
+};
+
+/** Elements consist of (1) directory relation and (2) whether it is pointing only to inherited dependees. */
+typedef std::vector< std::pair< std::unique_ptr<DirRelation>, bool> > DirRelations;
+
+/** Returns a DOT color name according to the directory depth. */
+static QCString getDirectoryBackgroundColor(int depthIndex)
+{
+  static int hue   = Config_getInt(HTML_COLORSTYLE_HUE);
+  static int sat   = Config_getInt(HTML_COLORSTYLE_SAT);
+  static int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA);
+  assert(depthIndex>=0 && depthIndex<=Config_getInt(DIR_GRAPH_MAX_DEPTH));
+  float fraction = (float)depthIndex/(float)Config_getInt(DIR_GRAPH_MAX_DEPTH);
+  const char hex[] = "0123456789abcdef";
+  int range = 0x40; // range from darkest color to lightest color
+  int luma   = 0xef-(int)(fraction*range); // interpolation
+  double r,g,b;
+  ColoredImage::hsl2rgb(hue/360.0,sat/255.0,
+                        pow(luma/255.0,gamma/100.0),&r,&g,&b);
+  int red   = (int)(r*255.0);
+  int green = (int)(g*255.0);
+  int blue  = (int)(b*255.0);
+  assert(red>=0   && red<=255);
+  assert(green>=0 && green<=255);
+  assert(blue>=0  && blue<=255);
+  char colStr[8];
+  colStr[0]='#';
+  colStr[1]=hex[red>>4];
+  colStr[2]=hex[red&0xf];
+  colStr[3]=hex[green>>4];
+  colStr[4]=hex[green&0xf];
+  colStr[5]=hex[blue>>4];
+  colStr[6]=hex[blue&0xf];
+  colStr[7]=0;
+  //printf("i=%d max=%d fraction=%f luma=%d %02x %02x %02x -> color=%s\n",
+  //    depthIndex,Config_getInt(DIR_GRAPH_MAX_DEPTH),fraction,luma,red,green,blue,colStr);
+  return colStr;
+}
+
+/** Returns a DOT color name according to the directory properties. */
+static const char* getDirectoryBorderColor(const DotDirProperty &property)
+{
+  if (property.isTruncated && property.isOrphaned)
+  {
+    return "red";
+  }
+  else if (property.isTruncated)
+  {
+    return "red";
+  }
+  else if (property.isOrphaned)
+  {
+    return "grey50";
+  }
+  else
+  {
+    return "grey25";
+  }
+}
+
+/** Returns a DOT node style according to the directory properties. */
+static std::string getDirectoryBorderStyle(const DotDirProperty &property)
+{
+  std::string style;
+  if (!property.isPeripheral)
+  {
+    style += "filled,";
+  }
+  if (property.isOriginal)
+  {
+    style += "bold,";
+  }
+  if (property.isIncomplete)
+  {
+    style += "dashed,";
+  }
+  else if (property.isTruncated && property.isOrphaned)
+  {
+    style += "dashed,";
+  }
+  return style;
+}
+
 /**
  * Puts DOT code for drawing directory to stream and adds it to the list.
- * @param[in,out] outStream stream to which the DOT code is written to
+ * @param[in,out] t stream to which the DOT code is written to
  * @param[in] directory will be mapped to a node in DOT code
- * @param[in] fillBackground if the node shall be explicitly filled
+ * @param[in] property are evaluated for formatting
  * @param[in,out] directoriesInGraph lists the directories which have been written to the output stream
+ * @param[in] startLevel current level to calculate relative distances from to determine the background color
+ */
+static void drawDirectory(TextStream &t, const DirDef *const directory, const DotDirProperty &property,
+    DirDefMap &directoriesInGraph,int startLevel)
+{
+  t << "  " << directory->getOutputFileBase() << " ["
+      "shape=box, "
+      "label=\""     << directory->shortName()                                       << "\", "
+      "style=\""     << getDirectoryBorderStyle(property)                            << "\", "
+      "fillcolor=\"" << getDirectoryBackgroundColor(directory->level()-startLevel)   << "\", "
+      "color=\""     << getDirectoryBorderColor(property)                            << "\", "
+      "URL=\""       << addHtmlExtensionIfMissing(directory->getOutputFileBase())    << "\""
+      "];\n";
+  directoriesInGraph.insert(std::make_pair(directory->getOutputFileBase().str(), directory));
+}
+
+/** Checks, if the directory is a the maximum drawn directory level. */
+static bool isAtMaxDepth(const DirDef *const directory, const int startLevel)
+{
+  return (directory->level() - startLevel) >= Config_getInt(DIR_GRAPH_MAX_DEPTH);
+}
+
+/**
+ * Writes DOT code for opening a cluster subgraph to stream.
+ *
+ * Ancestor clusters directly get a label. Other clusters get a plain text node with a label instead.
+ * This is because the plain text node can be used to draw dependency relationships.
  */
-static void drawDirectory(TextStream &outStream, const DirDef *const directory, const bool fillBackground,
-    DirDefMap &directoriesInGraph)
+static void drawClusterOpening(TextStream &outputStream, const DirDef *const directory,
+    const DotDirProperty &directoryProperty, DirDefMap &directoriesInGraph, const bool isAncestor,int startLevel)
 {
-  outStream << "  " << directory->getOutputFileBase() << " [shape=box "
-      "label=\"" << directory->shortName() << "\" ";
-  if (fillBackground)
+  outputStream << "  subgraph cluster" << directory->getOutputFileBase() << " {\n"
+      "    graph [ "
+      "bgcolor=\""  << getDirectoryBackgroundColor(directory->level()-startLevel) << "\", "
+      "pencolor=\"" << getDirectoryBorderColor(directoryProperty) << "\", "
+      "style=\""    << getDirectoryBorderStyle(directoryProperty) << "\", "
+      "label=\"";
+  if (isAncestor)
   {
-    outStream << "fillcolor=\"white\" style=\"filled\" ";
+    outputStream << directory->shortName();
   }
-  if (directory->isCluster())
+  outputStream << "\", "
+      "fontname=\"" << Config_getString(DOT_FONTNAME) << "\", "
+      "fontsize=\"" << Config_getInt(DOT_FONTSIZE) << "\", "
+      "URL=\"" << addHtmlExtensionIfMissing(directory->getOutputFileBase()) << "\""
+      "]\n";
+  if (!isAncestor)
   {
-    outStream << "color=\"red\" ";
+    outputStream << "    " << directory->getOutputFileBase() << " [shape=plaintext, "
+        "label=\"" << directory->shortName() << "\""
+        "];\n";
+    directoriesInGraph.insert(std::make_pair(directory->getOutputFileBase().str(), directory));
   }
-  outStream << "URL=\"" << directory->getOutputFileBase() << Doxygen::htmlFileExtension << "\"];\n";
-  directoriesInGraph.insert(std::make_pair(directory->getOutputFileBase().str(), directory));
 }
 
-void writeDotDirDepGraph(TextStream &t,const DirDef *dd,bool linkRelations)
+static void drawClusterClosing(TextStream &t)
+{
+  t << "  }\n";
+}
+
+/**
+ * Assembles a list of the directory relations and whether or not they result from "inheritance".
+ * @param dependencies Array to add the dependencies to.
+ * @param srcDir is the source of the dependency.
+ * @param isLeaf true, if no children are drawn for this directory.
+ */
+static void addDependencies(DirRelations &dependencies,const DirDef *const srcDir, bool isLeaf)
 {
-  int fontSize = Config_getInt(DOT_FONTSIZE);
-  QCString fontName = Config_getString(DOT_FONTNAME);
-  t << "digraph \"" << dd->displayName() << "\" {\n";
-  if (Config_getBool(DOT_TRANSPARENT))
+  for (const auto &usedDirectory : srcDir->usedDirs())
   {
-    t << "  bgcolor=transparent;\n";
+    const auto dstDir = usedDirectory->dir();
+    if (!dstDir->isParentOf(srcDir) && (isLeaf || usedDirectory->hasDirectSrcDeps()))
+    {
+      QCString relationName;
+      relationName.sprintf("dir_%06d_%06d", srcDir->dirCount(), dstDir->dirCount());
+      bool directRelation = isLeaf ? usedDirectory->hasDirectDstDeps() : usedDirectory->hasDirectDeps();
+      auto &&dependency = std::make_unique<DirRelation>(relationName, srcDir, usedDirectory.get());
+      auto &&pair = std::make_pair(std::move(dependency),directRelation);
+      dependencies.emplace_back(std::move(pair));
+    }
   }
-  t << "  compound=true\n";
-  t << "  node [ fontsize=\"" << fontSize << "\", fontname=\"" << fontName << "\"];\n";
-  t << "  edge [ labelfontsize=\"" << fontSize << "\", labelfontname=\"" << fontName << "\"];\n";
+}
 
+/** Recursively draws directory tree. */
+static void drawTree(DirRelations &dependencies, TextStream &t, const DirDef *const directory,
+    int startLevel, DirDefMap &directoriesInGraph, const bool isTreeRoot)
+{
+  if (!directory->hasSubdirs())
+  {
+    const DotDirProperty directoryProperty = DotDirPropertyBuilder().makeOriginal(isTreeRoot);
+    drawDirectory(t, directory, directoryProperty, directoriesInGraph,startLevel);
+    addDependencies(dependencies, directory, true);
+  }
+  else
+  {
+    if (isAtMaxDepth(directory, startLevel)) // maximum nesting level reached
+    {
+      const DotDirProperty directoryProperty = DotDirPropertyBuilder().makeOriginal(isTreeRoot);
+      drawDirectory(t, directory, directoryProperty, directoriesInGraph,startLevel);
+      addDependencies(dependencies, directory, true);
+    }
+    else // start a new nesting level
+    {
+      // open cluster
+      {
+        const DotDirProperty directoryProperty = DotDirPropertyBuilder().makeOriginal(isTreeRoot);
+        drawClusterOpening(t, directory, directoryProperty, directoriesInGraph, false, startLevel);
+        addDependencies(dependencies, directory, false);
+      }
+
+      // process all sub directories
+      for (const auto subDirectory : directory->subDirs())
+      {
+        drawTree(dependencies, t, subDirectory, startLevel, directoriesInGraph, false);
+      }
+
+      // close cluster
+      {
+        drawClusterClosing(t);
+      }
+    }
+  }
+}
+
+/**
+ * Write DOT code for directory dependency graph.
+ *
+ * Code is generated for a directory. Successors (sub-directories) of this directory are recursively drawn.
+ * Recursion is limited by `DIR_GRAPH_MAX_DEPTH`. The dependencies of those directories
+ * are drawn.
+ *
+ * If a dependee is not part of directory tree above, then the dependency is drawn to the first parent of the
+ * dependee, whose parent is an ancestor (sub-directory) of the original directory.
+ *
+ * @param t stream where the DOT code is written to
+ * @param dd directory for which the graph is generated for
+ * @param linkRelations if true, hyperlinks to the list of file dependencies are added
+ */
+void writeDotDirDepGraph(TextStream &t,const DirDef *dd,bool linkRelations)
+{
   DirDefMap dirsInGraph;
 
   dirsInGraph.insert(std::make_pair(dd->getOutputFileBase().str(),dd));
 
-  std::vector<const DirDef *> usedDirsNotDrawn;
-  for(const auto& usedDir : dd->usedDirs())
+  std::vector<const DirDef *> usedDirsNotDrawn, usedDirsDrawn;
+  for (const auto& usedDir : dd->usedDirs())
   {
     usedDirsNotDrawn.push_back(usedDir->dir());
   }
 
+  auto moveDrawnDirs = [&usedDirsDrawn,&usedDirsNotDrawn](const std::vector<const DirDef *>::iterator &newEnd)
+  {
+    // usedDirsNotDrawn is split into two segments: [begin()....newEnd-1] and [newEnd....end()]
+    // where the second segment starting at newEnd has been drawn, so append this segment to the usedDirsDrawn list and
+    // remove it from the usedDirsNotDrawn list.
+    std::move(newEnd, std::end(usedDirsNotDrawn), std::back_inserter(usedDirsDrawn));
+    usedDirsNotDrawn.erase(newEnd, usedDirsNotDrawn.end());
+  };
+
+  // if dd has a parent draw it as the outer layer
   const auto parent = dd->parent();
   if (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";
+    const DotDirProperty parentDirProperty = DotDirPropertyBuilder().
+                                             makeIncomplete().
+                                             makeOrphaned(parent->parent()!=nullptr);
+    drawClusterOpening(t, parent, parentDirProperty, dirsInGraph, true, parent->level());
 
     {
       // draw all directories which have `dd->parent()` as parent and `dd` as dependent
-      const auto newEnd = std::remove_if(usedDirsNotDrawn.begin(), usedDirsNotDrawn.end(), [&](const DirDef *const usedDir)
-      {
-        if (dd!=usedDir && dd->parent()==usedDir->parent())
+      const auto newEnd = std::stable_partition(usedDirsNotDrawn.begin(), usedDirsNotDrawn.end(),
+        [&](const DirDef *const usedDir)
         {
-          drawDirectory(t, usedDir, usedDir->isCluster() && !Config_getBool(DOT_TRANSPARENT), dirsInGraph);
-          return true;
-        }
-        return false;
-      }
-      );
-      usedDirsNotDrawn.erase(newEnd, usedDirsNotDrawn.end());
+          if (dd!=usedDir && dd->parent()==usedDir->parent()) // usedDir and dd share the same parent
+          {
+            const DotDirProperty usedDirProperty = DotDirPropertyBuilder().makeTruncated(usedDir->hasSubdirs());
+            drawDirectory(t, usedDir, usedDirProperty, dirsInGraph, parent->level());
+            return false; // part of the drawn partition
+          }
+          return true; // part of the not-drawn partition
+        });
+      moveDrawnDirs(newEnd);
     }
   }
-  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
-    for(const auto sdir : dd->subDirs())
-    {
-      drawDirectory(t, sdir, true, dirsInGraph);
-    }
-    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())
+  // draw the directory tree with dd as root
+  DirRelations dependencies;
+  drawTree(dependencies, t, dd, dd->level(), dirsInGraph, true);
+
+  if (parent)
   {
-    t << "  }\n";
+    drawClusterClosing(t);
   }
 
-  // add nodes for other used directories
+  // add nodes for other used directories (i.e. outside of the cluster of directories directly connected to dd)
   {
-    //printf("*** For dir %s\n",qPrint(shortName()));
-    for (const auto &usedDir : usedDirsNotDrawn)
-      // for each used dir (=directly used or a parent of a directly used dir)
-    {
-      const DirDef *dir=dd;
-      while (dir)
-      {
-        //printf("*** check relation %s->%s same_parent=%d !%s->isParentOf(%s)=%d\n",
-        //    qPrint(dir->shortName()),qPrint(usedDir->shortName()),
-        //    dir->parent()==usedDir->parent(),
-        //    qPrint(usedDir->shortName()),
-        //    qPrint(shortName()),
-        //    !usedDir->isParentOf(this)
-        //    );
-        if (dir!=usedDir && dir->parent()==usedDir->parent())
-          // include if both have the same parent (or no parent)
-        {
-          drawDirectory(t, usedDir, usedDir->isCluster() && !Config_getBool(DOT_TRANSPARENT), dirsInGraph);
-          break;
-        }
-        dir=dir->parent();
-      }
-    }
+    const auto newEnd = std::stable_partition(usedDirsNotDrawn.begin(), usedDirsNotDrawn.end(),
+     [&](const DirDef *const usedDir) // for each used dir (=directly used or a parent of a directly used dir)
+     {
+       const DirDef *dir=dd;
+       while (dir)
+       {
+         if (dir!=usedDir && dir->parent()==usedDir->parent()) // include if both have the same parent (or no parent)
+         {
+           const DotDirProperty usedDirProperty = DotDirPropertyBuilder().
+                                                  makeOrphaned(usedDir->parent()!=nullptr).
+                                                  makeTruncated(usedDir->hasSubdirs()).
+                                                  makePeripheral();
+           drawDirectory(t, usedDir, usedDirProperty, dirsInGraph, dir->level());
+           return false; // part of the drawn partition
+         }
+         dir=dir->parent();
+       }
+       return true; // part of the not-drawn partition
+     });
+    moveDrawnDirs(newEnd);
   }
 
   // add relations between all selected directories
-  for (const auto &kv : dirsInGraph) // foreach dir in the graph
   {
-    const DirDef *dir = kv.second;
-    for (const auto &udir : dir->usedDirs())
+    for (const auto &relationPair : dependencies)
     {
-      const DirDef *usedDir=udir->dir();
-      if ((dir!=dd || !udir->inherited()) &&     // only show direct dependencies for this dir
-        (usedDir!=dd || !udir->inherited()) && // only show direct dependencies for this dir
-        !usedDir->isParentOf(dir) &&             // don't point to own parent
-        dirsInGraph.find(usedDir->getOutputFileBase().str())!=dirsInGraph.end()) // only point to nodes that are in the graph
+      const auto &relation         = relationPair.first;
+      const bool directRelation    = relationPair.second;
+      const auto udir              = relation->destination();
+      const auto usedDir           = udir->dir();
+      const bool destIsSibling     = std::find(std::begin(usedDirsDrawn), std::end(usedDirsDrawn), usedDir) != std::end(usedDirsDrawn);
+      const bool destIsDrawn       = dirsInGraph.find(usedDir->getOutputFileBase().str())!=dirsInGraph.end(); // only point to nodes that are in the graph
+      const bool atMaxDepth        = isAtMaxDepth(usedDir, dd->level());
+
+      if (destIsSibling || (destIsDrawn && (directRelation || atMaxDepth)))
       {
-        QCString relationName;
-        relationName.sprintf("dir_%06d_%06d",dir->dirCount(),usedDir->dirCount());
+        const auto relationName = relation->getOutputFileBase();
+        const auto dir = relation->source();
         Doxygen::dirRelations.add(relationName,
             std::make_unique<DirRelation>(
-               relationName,dir,udir.get()));
+               relationName,dir,udir));
         size_t nrefs = udir->filePairs().size();
         t << "  " << dir->getOutputFileBase() << "->"
           << usedDir->getOutputFileBase();
         t << " [headlabel=\"" << (uint)nrefs << "\", labeldistance=1.5";
         if (linkRelations)
         {
-          t << " headhref=\"" << relationName << Doxygen::htmlFileExtension << "\"";
+          t << " headhref=\"" << addHtmlExtensionIfMissing(relationName) << "\"";
         }
         t << "];\n";
       }
     }
   }
-
-  t << "}\n";
 }
 
 DotDirDeps::DotDirDeps(const DirDef *dir) : m_dir(dir)
@@ -200,7 +412,10 @@ void DotDirDeps::computeTheGraph()
 {
   // compute md5 checksum of the graph were are about to generate
   TextStream md5stream;
+  writeGraphHeader(md5stream, m_dir->displayName());
+  md5stream << "  compound=true\n";
   writeDotDirDepGraph(md5stream,m_dir,m_linkRelations);
+  writeGraphFooter(md5stream);
   m_theGraph = md5stream.str();
 }
 
@@ -214,15 +429,9 @@ QCString DotDirDeps::getImgAltText() const
   return convertToXML(m_dir->displayName());
 }
 
-QCString DotDirDeps::writeGraph(TextStream &out,
-  GraphOutputFormat graphFormat,
-  EmbeddedOutputFormat textFormat,
-  const QCString &path,
-  const QCString &fileName,
-  const QCString &relPath,
-  bool generateImageMap,
-  int graphId,
-  bool linkRelations)
+QCString DotDirDeps::writeGraph(TextStream &out, GraphOutputFormat graphFormat, EmbeddedOutputFormat textFormat,
+                                const QCString &path, const QCString &fileName, const QCString &relPath, bool generateImageMap,
+                                int graphId, bool linkRelations)
 {
   m_linkRelations = linkRelations;
   m_urlOnly = TRUE;
index 4f915f9..b3fe517 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef DOTDIRDEPS_H
 #define DOTDIRDEPS_H
 
+#include <memory>
+
 #include "dotgraph.h"
 #include "dirdef.h"
 
@@ -48,4 +50,6 @@ class DotDirDeps : public DotGraph
     bool m_linkRelations = false;
 };
 
+using DotDirDepsPtr = std::shared_ptr<DotDirDeps>;
+
 #endif
index 5b0c68c..dcb3ecb 100644 (file)
@@ -153,7 +153,7 @@ static QCString replaceRef(const QCString &buf,const QCString &relPath,
         std::unique_ptr<DocRef>     df     { createRef( *parser.get(), link.mid(5), context ) };
         result+=externalRef(relPath,df->ref(),TRUE);
         if (!df->file().isEmpty())
-          result += df->file() + Doxygen::htmlFileExtension;
+          result += addHtmlExtensionIfMissing(df->file());
         if (!df->anchor().isEmpty())
           result += "#" + df->anchor();
         result += "\"";
index 025e7cb..1668761 100644 (file)
@@ -250,11 +250,7 @@ DotGfxHierarchyTable::DotGfxHierarchyTable(const QCString &prefix,ClassDef::Comp
         n->markAsVisible();
         n->colorConnectedNodes(curColor);
         curColor++;
-        const DotNode *dn=n->findDocNode();
-        if (dn!=0)
-          m_rootSubgraphs.push_back(const_cast<DotNode*>(dn));
-        else
-          m_rootSubgraphs.push_back(n);
+        m_rootSubgraphs.push_back(n);
       }
     }
   }
index 0d37881..dfec97a 100644 (file)
@@ -56,5 +56,6 @@ class DotGfxHierarchyTable : public DotGraph
     DotNode *              m_rootSubgraphNode;
 };
 
+using DotGfxHierarchyTablePtr = std::shared_ptr<DotGfxHierarchyTable>;
 
 #endif
index f8cb194..f55a8d9 100644 (file)
@@ -182,7 +182,7 @@ bool DotGraph::prepareDotFile()
   {
     // run dot to create a bitmap image
     DotRunner * dotRun = DotManager::instance()->createRunner(absDotName(), sigStr);
-    dotRun->addJob(Config_getEnum(DOT_IMAGE_FORMAT), absImgName(), absDotName(), 1);
+    dotRun->addJob(Config_getEnumAsString(DOT_IMAGE_FORMAT), absImgName(), absDotName(), 1);
     if (m_generateImageMap) dotRun->addJob(MAP_CMD, absMapName(), absDotName(), 1);
   }
   else if (m_graphFormat == GOF_EPS)
index d409d50..58dd75b 100644 (file)
@@ -101,7 +101,7 @@ void DotGroupCollaboration::buildGraph(const GroupDef* gd)
   // Add classes
   for (const auto &def : gd->getClasses())
   {
-    tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
+    tmp_url = def->getReference()+"$"+addHtmlExtensionIfMissing(def->getOutputFileBase());
     if (!def->anchor().isEmpty())
     {
       tmp_url+="#"+def->anchor();
@@ -112,21 +112,21 @@ void DotGroupCollaboration::buildGraph(const GroupDef* gd)
   // Add namespaces
   for (const auto &def : gd->getNamespaces())
   {
-    tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
+    tmp_url = def->getReference()+"$"+addHtmlExtensionIfMissing(def->getOutputFileBase());
     addCollaborationMember( def, tmp_url, DotGroupCollaboration::tnamespace );
   }
 
   // Add files
   for (const auto &def : gd->getFiles())
   {
-    tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
+    tmp_url = def->getReference()+"$"+addHtmlExtensionIfMissing(def->getOutputFileBase());
     addCollaborationMember( def, tmp_url, DotGroupCollaboration::tfile );
   }
 
   // Add pages
   for (const auto &def : gd->getPages())
   {
-    tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
+    tmp_url = def->getReference()+"$"+addHtmlExtensionIfMissing(def->getOutputFileBase());
     addCollaborationMember( def, tmp_url, DotGroupCollaboration::tpages );
   }
 
@@ -135,7 +135,7 @@ void DotGroupCollaboration::buildGraph(const GroupDef* gd)
   {
     for(const auto def : gd->getDirs())
     {
-      tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
+      tmp_url = def->getReference()+"$"+addHtmlExtensionIfMissing(def->getOutputFileBase());
       addCollaborationMember( def, tmp_url, DotGroupCollaboration::tdir );
     }
   }
@@ -146,7 +146,7 @@ void DotGroupCollaboration::addMemberList( MemberList* ml )
   if ( ml==0 || ml->empty() ) return;
   for (const auto &def : *ml)
   {
-    QCString tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension
+    QCString tmp_url = def->getReference()+"$"+addHtmlExtensionIfMissing(def->getOutputFileBase());
       +"#"+def->anchor();
     addCollaborationMember( def, tmp_url, DotGroupCollaboration::tmember );
   }
index 872e7f7..ddb12bb 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef DOTGROUPCOLLABORATION_H
 #define DOTGROUPCOLLABORATION_H
 
+#include <memory>
+
 #include "dotnode.h"
 #include "dotgraph.h"
 #include "groupdef.h"
@@ -83,4 +85,6 @@ class DotGroupCollaboration : public DotGraph
     std::vector< std::unique_ptr<Edge> >     m_edges;
 };
 
+using DotGroupCollaborationPtr = std::shared_ptr<DotGroupCollaboration>;
+
 #endif
index a0e58bf..aa340ab 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef DOTINCLDEPGRAPH_H
 #define DOTINCLDEPGRAPH_H
 
+#include <memory>
+
 #include "qcstring.h"
 #include "filedef.h"
 
@@ -57,4 +59,6 @@ class DotInclDepGraph : public DotGraph
     bool            m_inverse;
 };
 
+using DotInclDepGraphPtr = std::shared_ptr<DotInclDepGraph>;
+
 #endif
index bfc7c08..b91f111 100644 (file)
@@ -96,30 +96,6 @@ static EdgeProperties umlEdgeProps =
   umlEdgeColorMap, umlArrowStyleMap, umlEdgeStyleMap
 };
 
-// Extracted from config setting "DOT_UML_DETAILS"
-enum class UmlDetailLevel
-{
-  Default, // == NO, the default setting
-  Full,    // == YES, include type and arguments
-  None     // == NONE, don't include compartments for attributes and methods
-};
-
-// Local helper function for extracting the configured detail level
-static UmlDetailLevel getUmlDetailLevelFromConfig()
-{
-  UmlDetailLevel result = UmlDetailLevel::Default;
-  QCString umlDetailsStr = Config_getEnum(DOT_UML_DETAILS).upper();
-  if (umlDetailsStr == "YES")
-  {
-    result=UmlDetailLevel::Full;
-  }
-  else if (umlDetailsStr == "NONE")
-  {
-    result=UmlDetailLevel::None;
-  }
-  return result;
-}
-
 static QCString escapeTooltip(const QCString &tooltip)
 {
   if (tooltip.isEmpty()) return tooltip;
@@ -155,6 +131,7 @@ static void writeBoxMemberList(TextStream &t,
     }
 
     int count=0;
+    static auto dotUmlDetails = Config_getEnum(DOT_UML_DETAILS);
     for (const auto &mma : *ml)
     {
       if (mma->getClassDef() == scope &&
@@ -170,7 +147,7 @@ static void writeBoxMemberList(TextStream &t,
         {
           t << prot << " ";
           QCString label;
-          if(getUmlDetailLevelFromConfig()==UmlDetailLevel::Full)
+          if (dotUmlDetails==DOT_UML_DETAILS_t::YES)
           {
             label+=mma->typeString();
             label+=" ";
@@ -178,7 +155,7 @@ static void writeBoxMemberList(TextStream &t,
           label+=mma->name();
           if (!mma->isObjCMethod() && (mma->isFunction() || mma->isSlot() || mma->isSignal()))
           {
-            if(getUmlDetailLevelFromConfig()==UmlDetailLevel::Full)
+            if (dotUmlDetails==DOT_UML_DETAILS_t::YES)
             {
               label+=mma->argsString();
             }
@@ -382,9 +359,27 @@ void DotNode::writeBox(TextStream &t,
                        GraphOutputFormat /*format*/,
                        bool hasNonReachableChildren) const
 {
-  const char *labCol =
-    m_url.isEmpty() ? "grey75" :  // non link
+  const char *labCol;
+  if (m_classDef)
+  {
+    if (m_classDef->hasDocumentation() && hasNonReachableChildren)
+      labCol = "red";
+    else if (m_classDef->hasDocumentation() && !hasNonReachableChildren)
+      labCol = "black";
+    else if (!m_classDef->hasDocumentation() && hasNonReachableChildren)
+      labCol = "orangered";
+    else // (!m_classDef->hasDocumentation() && !hasNonReachableChildren)
+    {
+      labCol = "grey75";
+      if (m_classDef->templateMaster() && m_classDef->templateMaster()->hasDocumentation())
+        labCol = "black";
+    }
+  }
+  else
+  {
+    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))
@@ -413,7 +408,8 @@ void DotNode::writeBox(TextStream &t,
 
     //printf("DotNode::writeBox for %s\n",qPrint(m_classDef->name()));
     t << "{" << convertLabel(m_label) << "\\n";
-    if (getUmlDetailLevelFromConfig()!=UmlDetailLevel::None)
+    static auto dotUmlDetails = Config_getEnum(DOT_UML_DETAILS);
+    if (dotUmlDetails!=DOT_UML_DETAILS_t::NONE)
     {
       t << "|";
       writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubAttribs),m_classDef,FALSE,&arrowNames);
@@ -467,26 +463,22 @@ void DotNode::writeBox(TextStream &t,
   }
   else
   {
+    t << ",color=\"" << labCol << "\"";
     if (!Config_getBool(DOT_TRANSPARENT))
     {
-      t << ",color=\"" << labCol << "\", fillcolor=\"";
-      t << "white";
-      t << "\", style=\"filled\"";
-    }
-    else
-    {
-      t << ",color=\"" << labCol << "\"";
+      t << ", fillcolor=\"white\"";
+      t << ", style=\"filled\"";
     }
     if (!m_url.isEmpty())
     {
       int anchorPos = m_url.findRev('#');
       if (anchorPos==-1)
       {
-        t << ",URL=\"" << m_url << Doxygen::htmlFileExtension << "\"";
+        t << ",URL=\"" << addHtmlExtensionIfMissing(m_url) << "\"";
       }
       else
       {
-        t << ",URL=\"" << m_url.left(anchorPos) << Doxygen::htmlFileExtension
+        t << ",URL=\"" << addHtmlExtensionIfMissing(m_url.left(anchorPos))
           << m_url.right(m_url.length()-anchorPos) << "\"";
       }
     }
@@ -816,43 +808,38 @@ void DotNode::colorConnectedNodes(int curColor)
   }
 }
 
+#define DEBUG_RENUMBERING 0
+
 void DotNode::renumberNodes(int &number)
 {
-  m_number = number++;
-  for (const auto &cn : m_children)
+  if (!isRenumbered())
   {
-    if (!cn->isRenumbered())
+#if DEBUG_RENUMBERING
+    static int level = 0;
+    printf("%3d: ",subgraphId());
+    for (int i = 0; i < level; i++) printf("  ");
+    printf("> %s old = %d new = %d\n",qPrint(m_label),m_number,number);
+    level++;
+#endif
+    m_number = number++;
+    markRenumbered();
+    for (const auto &cn : m_children)
     {
-      cn->markRenumbered();
       cn->renumberNodes(number);
     }
-  }
-}
-
-const DotNode *DotNode::findDocNode() const
-{
-  if (!m_url.isEmpty()) return this;
-  //printf("findDocNode(): '%s'\n",qPrint(m_label));
-  for (const auto &pn : m_parents)
-  {
-    if (!pn->hasDocumentation())
-    {
-      pn->markHasDocumentation();
-      const DotNode *dn = pn->findDocNode();
-      if (dn) return dn;
-    }
-  }
-  for (const auto &cn : m_children)
-  {
-    if (!cn->hasDocumentation())
+    for (const auto &pn : m_parents)
     {
-      cn->markHasDocumentation();
-      const DotNode *dn = cn->findDocNode();
-      if (dn) return dn;
+      pn->renumberNodes(number);
     }
+#if DEBUG_RENUMBERING
+    level--;
+    printf("%3d: ",subgraphId());
+    for (int i = 0; i < level; i++) printf("  ");
+    printf("< %s assigned = %d\n",qPrint(m_label),m_number);
+#endif
   }
-  return 0;
 }
 
 
 
+
index cd1e75b..c630951 100644 (file)
@@ -104,7 +104,6 @@ class DotNode
 
     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 DotNodeRefVector &children() const { return m_children; }
index 87eb5fc..4686fce 100644 (file)
@@ -308,15 +308,7 @@ static void addRelatedPage(Entry *root)
     if (!g.groupname.isEmpty() && (gd=Doxygen::groupLinkedMap->find(g.groupname))) break;
   }
   //printf("---> addRelatedPage() %s gd=%p\n",qPrint(root->name),gd);
-  QCString doc;
-  if (root->brief.isEmpty())
-  {
-    doc=root->doc+root->inbodyDocs;
-  }
-  else
-  {
-    doc=root->brief+"\n\n"+root->doc+root->inbodyDocs;
-  }
+  QCString doc=root->doc+root->inbodyDocs;
 
   PageDef *pd = addRelatedPage(root->name,root->args,doc,
       root->docFile,
@@ -1244,6 +1236,7 @@ static void addConceptToContext(const Entry *root)
       cd->setLanguage(root->lang);
       cd->setId(root->id);
       cd->setHidden(root->hidden);
+      cd->setGroupId(root->mGrpId);
       if (tArgList)
       {
         cd->setTemplateArguments(*tArgList);
@@ -1307,6 +1300,37 @@ static void buildConceptDocList(const Entry *root)
   for (const auto &e : root->children()) buildConceptDocList(e.get());
 }
 
+// This routine is to allow @ingroup X @{ concept A; concept B; @} to work
+// (same also works for variable and functions because of logic in MemberGroup::insertMember)
+static void distributeConceptGroups()
+{
+  for (const auto &cd : *Doxygen::conceptLinkedMap)
+  {
+    if (cd->groupId()!=DOX_NOGROUP)
+    {
+      for (const auto &ocd : *Doxygen::conceptLinkedMap)
+      {
+        if (cd!=ocd && cd->groupId()==ocd->groupId() &&
+            !cd->partOfGroups().empty() && ocd->partOfGroups().empty())
+        {
+          ConceptDefMutable *ocdm = toConceptDefMutable(ocd.get());
+          if (ocdm)
+          {
+            for (const auto &gd : cd->partOfGroups())
+            {
+              if (gd)
+              {
+                ocdm->makePartOfGroup(gd);
+                const_cast<GroupDef*>(gd)->addConcept(ocd.get());
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
 //----------------------------------------------------------------------
 
 static void resolveClassNestingRelations()
@@ -3612,6 +3636,11 @@ static void buildFunctionList(const Entry *root)
                   sameRequiresClause = FALSE;
                 }
               }
+              else if (!mdTempl.empty() || !root->tArgLists.empty())
+              { // if one has template parameters and the other doesn't then that also counts as a
+                // difference
+                sameNumTemplateArgs = FALSE;
+              }
 
               bool staticsInDifferentFiles =
                 root->stat && md->isStatic() && root->fileName!=md->getDefFileName();
@@ -4101,7 +4130,7 @@ static void findUsedClassesForClass(const Entry *root,
           }
           // add any template arguments to the class
           QCString usedName = removeRedundantWhiteSpace(usedClassName+templSpec);
-          //printf("    usedName=%s\n",qPrint(usedName));
+          //printf("    usedName=%s usedClassName=%s templSpec=%s\n",qPrint(usedName),qPrint(usedClassName),qPrint(templSpec));
 
           TemplateNameMap formTemplateNames;
           if (templateNames.empty())
@@ -5114,7 +5143,7 @@ static void addMemberDocs(const Entry *root,
 {
   if (md==0) return;
   //printf("addMemberDocs: '%s'::'%s' '%s' funcDecl='%s' mSpec=%lld\n",
-  //     qPrint(root->parent()->name),qPrint(md->name()),md->argsString(),funcDecl,spec);
+  //     qPrint(root->parent()->name),qPrint(md->name()),qPrint(md->argsString()),qPrint(funcDecl),spec);
   QCString fDecl=funcDecl;
   // strip extern specifier
   fDecl.stripPrefix("extern ");
@@ -5579,7 +5608,7 @@ static QCString substituteTemplatesInString(
   dst+=src.substr(p);
   //printf("  substituteTemplatesInString(%s)=%s\n",
   //    qPrint(src),qPrint(dst));
-  return dst;
+  return QCString(dst);
 }
 
 static void substituteTemplatesInArgList(
@@ -6642,7 +6671,7 @@ static void findMember(const Entry *root,
               root->fileName,root->startLine,root->startColumn,
               funcType,funcName,funcArgs,exceptions,
               root->protection,root->virt,
-              root->stat && !isMemberOf,
+              root->stat,
               isMemberOf ? Foreign : Related,
               mtype,
               (!root->tArgLists.empty() ? root->tArgLists.back() : ArgumentList()),
@@ -7575,7 +7604,7 @@ static void findDocumentedEnumValues()
 
 static void addMembersToIndex()
 {
-  // for each member name
+  // for each class member name
   for (const auto &mn : *Doxygen::memberNameLinkedMap)
   {
     // for each member definition
@@ -7584,7 +7613,7 @@ static void addMembersToIndex()
       addClassMemberNameToIndex(md.get());
     }
   }
-  // for each member name
+  // for each file/namespace function name
   for (const auto &mn : *Doxygen::functionNameLinkedMap)
   {
     // for each member definition
@@ -7605,6 +7634,164 @@ static void addMembersToIndex()
 
 //----------------------------------------------------------------------
 
+static void addToIndices()
+{
+  for (const auto &cd : *Doxygen::classLinkedMap)
+  {
+    if (cd->isLinkableInProject())
+    {
+      Doxygen::indexList->addIndexItem(cd.get(),0);
+      if (Doxygen::searchIndex)
+      {
+        Doxygen::searchIndex->setCurrentDoc(cd.get(),cd->anchor(),FALSE);
+        Doxygen::searchIndex->addWord(cd->localName(),TRUE);
+      }
+    }
+  }
+
+  for (const auto &cd : *Doxygen::conceptLinkedMap)
+  {
+    if (cd->isLinkableInProject())
+    {
+      Doxygen::indexList->addIndexItem(cd.get(),0);
+      if (Doxygen::searchIndex)
+      {
+        Doxygen::searchIndex->setCurrentDoc(cd.get(),cd->anchor(),FALSE);
+        Doxygen::searchIndex->addWord(cd->localName(),TRUE);
+      }
+    }
+  }
+
+  for (const auto &nd : *Doxygen::namespaceLinkedMap)
+  {
+    if (nd->isLinkableInProject())
+    {
+      Doxygen::indexList->addIndexItem(nd.get(),0);
+      if (Doxygen::searchIndex)
+      {
+        Doxygen::searchIndex->setCurrentDoc(nd.get(),nd->anchor(),FALSE);
+        Doxygen::searchIndex->addWord(nd->localName(),TRUE);
+      }
+    }
+  }
+
+  for (const auto &fn : *Doxygen::inputNameLinkedMap)
+  {
+    for (const auto &fd : *fn)
+    {
+      if (Doxygen::searchIndex && fd->isLinkableInProject())
+      {
+        Doxygen::searchIndex->setCurrentDoc(fd.get(),fd->anchor(),FALSE);
+        Doxygen::searchIndex->addWord(fd->localName(),TRUE);
+      }
+    }
+  }
+
+  for (const auto &gd : *Doxygen::groupLinkedMap)
+  {
+    if (gd->isLinkableInProject())
+    {
+      Doxygen::indexList->addIndexItem(gd.get(),0,QCString(),gd->groupTitle());
+      if (Doxygen::searchIndex)
+      {
+        Doxygen::searchIndex->setCurrentDoc(gd.get(),gd->anchor(),FALSE);
+        std::string title = gd->groupTitle().str();
+        static const reg::Ex re(R"(\a[\w-]*)");
+        reg::Iterator it(title,re);
+        reg::Iterator end;
+        for (; it!=end ; ++it)
+        {
+          const auto &match = *it;
+          std::string matchStr = match.str();
+          Doxygen::searchIndex->addWord(matchStr.c_str(),TRUE);
+        }
+      }
+    }
+  }
+
+  for (const auto &pd : *Doxygen::pageLinkedMap)
+  {
+    if (pd->isLinkableInProject())
+    {
+      Doxygen::indexList->addIndexItem(pd.get(),0,QCString(),filterTitle(pd->title().str()));
+    }
+  }
+
+  auto addMemberToSearchIndex = [](const MemberDef *md)
+  {
+    if (Doxygen::searchIndex)
+    {
+      Doxygen::searchIndex->setCurrentDoc(md,md->anchor(),FALSE);
+      QCString ln=md->localName();
+      QCString qn=md->qualifiedName();
+      Doxygen::searchIndex->addWord(ln,TRUE);
+      if (ln!=qn)
+      {
+        Doxygen::searchIndex->addWord(qn,TRUE);
+        if (md->getClassDef())
+        {
+          Doxygen::searchIndex->addWord(md->getClassDef()->displayName(),TRUE);
+        }
+        if (md->getNamespaceDef())
+        {
+          Doxygen::searchIndex->addWord(md->getNamespaceDef()->displayName(),TRUE);
+        }
+      }
+    }
+  };
+
+  auto getScope = [](const MemberDef *md)
+  {
+    const Definition *scope = 0;
+    if (md->getGroupDef())          scope = md->getGroupDef();
+    else if (md->getClassDef())     scope = md->getClassDef();
+    else if (md->getNamespaceDef()) scope = md->getNamespaceDef();
+    else if (md->getFileDef())      scope = md->getFileDef();
+    return scope;
+  };
+
+  auto addMemberToIndices = [addMemberToSearchIndex,getScope](const MemberDef *md)
+  {
+    if (md->isLinkableInProject())
+    {
+      if (!(md->isEnumerate() && md->isAnonymous()))
+      {
+        Doxygen::indexList->addIndexItem(getScope(md),md);
+        addMemberToSearchIndex(md);
+      }
+      if (md->isEnumerate())
+      {
+        for (const auto &fmd : md->enumFieldList())
+        {
+          Doxygen::indexList->addIndexItem(getScope(fmd),fmd);
+          addMemberToSearchIndex(fmd);
+        }
+      }
+    }
+  };
+
+  // for each class member name
+  for (const auto &mn : *Doxygen::memberNameLinkedMap)
+  {
+    // for each member definition
+    for (const auto &md : *mn)
+    {
+      addMemberToIndices(md.get());
+    }
+  }
+  // for each file/namespace function name
+  for (const auto &mn : *Doxygen::functionNameLinkedMap)
+  {
+    // for each member definition
+    for (const auto &md : *mn)
+    {
+      addMemberToIndices(md.get());
+    }
+  }
+}
+
+//----------------------------------------------------------------------
+
 static void vhdlCorrectMemberProperties()
 {
   // for each member name
@@ -7670,7 +7857,7 @@ static void computeMemberRelations()
                    bmd->getLanguage()==SrcLangExt_Python || bmd->getLanguage()==SrcLangExt_Java || bmd->getLanguage()==SrcLangExt_PHP ||
                    bmcd->compoundType()==ClassDef::Interface || bmcd->compoundType()==ClassDef::Protocol
                   ) &&
-                  md->isFunction() &&
+                  (md->isFunction() || md->isCSharpProperty()) &&
                   mcd->isLinkable() &&
                   bmcd->isLinkable() &&
                   mcd->isBaseClass(bmcd,TRUE))
@@ -7924,14 +8111,17 @@ static void generateFileSources()
             auto ctx = std::make_shared<SourceContext>(fd.get(),generateSourceFile,*g_outputList);
             if (generateSourceFile)
             {
-              msg("Generating code for file %s...\n",qPrint(fd->docName()));
               fd->writeSourceHeader(ctx->ol);
             }
-            else
-            {
-              msg("Parsing code for file %s...\n",qPrint(fd->docName()));
-            }
             auto processFile = [ctx]() {
+              if (ctx->generateSourceFile)
+              {
+                msg("Generating code for file %s...\n",qPrint(ctx->fd->docName()));
+              }
+              else
+              {
+                msg("Parsing code for file %s...\n",qPrint(ctx->fd->docName()));
+              }
               StringVector filesInSameTu;
               ctx->fd->getAllIncludeFilesRecursively(filesInSameTu);
               if (ctx->generateSourceFile) // sources need to be shown in the output
@@ -7993,15 +8183,56 @@ static void generateFileDocs()
 
   if (!Doxygen::inputNameLinkedMap->empty())
   {
-    for (const auto &fn : *Doxygen::inputNameLinkedMap)
+    std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS));
+    if (numThreads==0)
+    {
+      numThreads = std::thread::hardware_concurrency();
+    }
+    if (numThreads>1) // multi threaded processing
     {
-      for (const auto &fd : *fn)
+      struct DocContext
+      {
+        DocContext(FileDef *fd_,OutputList ol_)
+          : fd(fd_), ol(ol_) {}
+        FileDef *fd;
+        OutputList ol;
+      };
+      ThreadPool threadPool(numThreads);
+      std::vector< std::future< std::shared_ptr<DocContext> > > results;
+      for (const auto &fn : *Doxygen::inputNameLinkedMap)
       {
-        bool doc = fd->isLinkableInProject();
-        if (doc)
+        for (const auto &fd : *fn)
         {
-          msg("Generating docs for file %s...\n",qPrint(fd->docName()));
-          fd->writeDocumentation(*g_outputList);
+          bool doc = fd->isLinkableInProject();
+          if (doc)
+          {
+            auto ctx = std::make_shared<DocContext>(fd.get(),*g_outputList);
+            auto processFile = [ctx]() {
+              msg("Generating docs for file %s...\n",qPrint(ctx->fd->docName()));
+              ctx->fd->writeDocumentation(ctx->ol);
+              return ctx;
+            };
+            results.emplace_back(threadPool.queue(processFile));
+          }
+        }
+      }
+      for (auto &f : results)
+      {
+        auto ctx = f.get();
+      }
+    }
+    else // single threaded processing
+    {
+      for (const auto &fn : *Doxygen::inputNameLinkedMap)
+      {
+        for (const auto &fd : *fn)
+        {
+          bool doc = fd->isLinkableInProject();
+          if (doc)
+          {
+            msg("Generating docs for file %s...\n",qPrint(fd->docName()));
+            fd->writeDocumentation(*g_outputList);
+          }
         }
       }
     }
@@ -8240,28 +8471,83 @@ static void countMembers()
 
 static void generateClassList(const ClassLinkedMap &classList)
 {
-  for (const auto &cdi : classList)
+  std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS));
+  if (numThreads==0)
   {
-    ClassDefMutable *cd=toClassDefMutable(cdi.get());
+    numThreads = std::thread::hardware_concurrency();
+  }
+  if (numThreads>1) // multi threaded processing
+  {
+    struct DocContext
+    {
+      DocContext(ClassDefMutable *cd_,OutputList ol_)
+        : cd(cd_), ol(ol_) {}
+      ClassDefMutable *cd;
+      OutputList ol;
+    };
+    ThreadPool threadPool(numThreads);
+    std::vector< std::future< std::shared_ptr<DocContext> > > results;
+    for (const auto &cdi : classList)
+    {
+      ClassDefMutable *cd=toClassDefMutable(cdi.get());
 
-    //printf("cd=%s getOuterScope=%p global=%p\n",qPrint(cd->name()),cd->getOuterScope(),Doxygen::globalScope);
-    if (cd &&
-        (cd->getOuterScope()==0 || // <-- should not happen, but can if we read an old tag file
-         cd->getOuterScope()==Doxygen::globalScope // only look at global classes
-        ) && !cd->isHidden() && !cd->isEmbeddedInOuterScope()
-       )
+      //printf("cd=%s getOuterScope=%p global=%p\n",qPrint(cd->name()),cd->getOuterScope(),Doxygen::globalScope);
+      if (cd &&
+          (cd->getOuterScope()==0 || // <-- should not happen, but can if we read an old tag file
+           cd->getOuterScope()==Doxygen::globalScope // only look at global classes
+          ) && !cd->isHidden() && !cd->isEmbeddedInOuterScope()
+         )
+      {
+        auto ctx = std::make_shared<DocContext>(cd,*g_outputList);
+        auto processFile = [ctx]()
+        {
+          msg("Generating docs for compound %s...\n",qPrint(ctx->cd->name()));
+
+          // skip external references, anonymous compounds and
+          // template instances
+          if ( ctx->cd->isLinkableInProject() && ctx->cd->templateMaster()==0)
+          {
+            ctx->cd->writeDocumentation(ctx->ol);
+            ctx->cd->writeMemberList(ctx->ol);
+          }
+
+          // even for undocumented classes, the inner classes can be documented.
+          ctx->cd->writeDocumentationForInnerClasses(ctx->ol);
+          return ctx;
+        };
+        results.emplace_back(threadPool.queue(processFile));
+      }
+    }
+    for (auto &f : results)
     {
-      // skip external references, anonymous compounds and
-      // template instances
-      if ( cd->isLinkableInProject() && cd->templateMaster()==0)
+      auto ctx = f.get();
+    }
+  }
+  else // single threaded processing
+  {
+    for (const auto &cdi : classList)
+    {
+      ClassDefMutable *cd=toClassDefMutable(cdi.get());
+
+      //printf("cd=%s getOuterScope=%p global=%p\n",qPrint(cd->name()),cd->getOuterScope(),Doxygen::globalScope);
+      if (cd &&
+          (cd->getOuterScope()==0 || // <-- should not happen, but can if we read an old tag file
+           cd->getOuterScope()==Doxygen::globalScope // only look at global classes
+          ) && !cd->isHidden() && !cd->isEmbeddedInOuterScope()
+         )
       {
-        msg("Generating docs for compound %s...\n",qPrint(cd->name()));
+        // skip external references, anonymous compounds and
+        // template instances
+        if ( cd->isLinkableInProject() && cd->templateMaster()==0)
+        {
+          msg("Generating docs for compound %s...\n",qPrint(cd->name()));
 
-        cd->writeDocumentation(*g_outputList);
-        cd->writeMemberList(*g_outputList);
+          cd->writeDocumentation(*g_outputList);
+          cd->writeMemberList(*g_outputList);
+        }
+        // even for undocumented classes, the inner classes can be documented.
+        cd->writeDocumentationForInnerClasses(*g_outputList);
       }
-      // even for undocumented classes, the inner classes can be documented.
-      cd->writeDocumentationForInnerClasses(*g_outputList);
     }
   }
 }
@@ -8479,6 +8765,9 @@ static void findSectionsInDocumentation()
   if (Doxygen::mainPage) Doxygen::mainPage->findSectionsInDocumentation();
 }
 
+//----------------------------------------------------------------------
+
+
 static void flushCachedTemplateRelations()
 {
   // remove all references to classes from the cache
@@ -9098,6 +9387,7 @@ static void generateExampleDocs()
                          pd->docLine(),                            // startLine
                          pd.get(),                                 // context
                          0,                                        // memberDef
+                         (pd->briefDescription().isEmpty()?"":pd->briefDescription()+"\n\n")+
                          pd->documentation()+"\n\n\\include"+lineNoOptStr+" "+pd->name(), // docs
                          TRUE,                                     // index words
                          TRUE,                                     // is example
@@ -9130,25 +9420,76 @@ static void generateGroupDocs()
 
 static void generateNamespaceClassDocs(const ClassLinkedRefMap &classList)
 {
-  // for each class in the namespace...
-  for (const auto &cd : classList)
+  std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS));
+  if (numThreads==0)
   {
-    ClassDefMutable *cdm = toClassDefMutable(cd);
-    if (cdm)
+    numThreads = std::thread::hardware_concurrency();
+  }
+  if (numThreads>1) // multi threaded processing
+  {
+    struct DocContext
     {
-      if ( ( cd->isLinkableInProject() &&
-             cd->templateMaster()==0
-           ) // skip external references, anonymous compounds and
-          // template instances and nested classes
-          && !cd->isHidden() && !cd->isEmbeddedInOuterScope()
-         )
+      DocContext(ClassDefMutable *cdm_,OutputList ol_)
+        : cdm(cdm_), ol(ol_) {}
+      ClassDefMutable *cdm;
+      OutputList ol;
+    };
+    ThreadPool threadPool(numThreads);
+    std::vector< std::future< std::shared_ptr<DocContext> > > results;
+    // for each class in the namespace...
+    for (const auto &cd : classList)
+    {
+      ClassDefMutable *cdm = toClassDefMutable(cd);
+      if (cdm)
+      {
+        auto ctx = std::make_shared<DocContext>(cdm,*g_outputList);
+        auto processFile = [ctx]()
+        {
+          if ( ( ctx->cdm->isLinkableInProject() &&
+                ctx->cdm->templateMaster()==0
+               ) // skip external references, anonymous compounds and
+              // template instances and nested classes
+              && !ctx->cdm->isHidden() && !ctx->cdm->isEmbeddedInOuterScope()
+             )
+          {
+            msg("Generating docs for compound %s...\n",qPrint(ctx->cdm->name()));
+            ctx->cdm->writeDocumentation(ctx->ol);
+            ctx->cdm->writeMemberList(ctx->ol);
+          }
+          ctx->cdm->writeDocumentationForInnerClasses(ctx->ol);
+          return ctx;
+        };
+        results.emplace_back(threadPool.queue(processFile));
+      }
+    }
+    // wait for the results
+    for (auto &f : results)
+    {
+      auto ctx = f.get();
+    }
+  }
+  else // single threaded processing
+  {
+    // for each class in the namespace...
+    for (const auto &cd : classList)
+    {
+      ClassDefMutable *cdm = toClassDefMutable(cd);
+      if (cdm)
       {
-        msg("Generating docs for compound %s...\n",qPrint(cd->name()));
+        if ( ( cd->isLinkableInProject() &&
+              cd->templateMaster()==0
+             ) // skip external references, anonymous compounds and
+            // template instances and nested classes
+            && !cd->isHidden() && !cd->isEmbeddedInOuterScope()
+           )
+        {
+          msg("Generating docs for compound %s...\n",qPrint(cd->name()));
 
-        cdm->writeDocumentation(*g_outputList);
-        cdm->writeMemberList(*g_outputList);
+          cdm->writeDocumentation(*g_outputList);
+          cdm->writeMemberList(*g_outputList);
+        }
+        cdm->writeDocumentationForInnerClasses(*g_outputList);
       }
-      cdm->writeDocumentationForInnerClasses(*g_outputList);
     }
   }
 }
@@ -9919,6 +10260,8 @@ static void readDir(FileInfo *fi,
   msg("Searching for files in directory %s\n", qPrint(fi->absFilePath()));
   //printf("killSet=%p count=%d\n",killSet,killSet ? (int)killSet->count() : -1);
 
+  StringVector dirResultList;
+
   for (const auto &dirEntry : dir.iterator())
   {
     FileInfo cfi(dirEntry.path());
@@ -9952,7 +10295,7 @@ static void readDir(FileInfo *fi,
             fn->push_back(std::move(fd));
           }
         }
-        if (resultList) resultList->push_back(fullName);
+        dirResultList.push_back(fullName);
         if (resultSet) resultSet->insert(fullName);
         if (killSet) killSet->insert(fullName);
       }
@@ -9964,17 +10307,20 @@ static void readDir(FileInfo *fi,
       {
         FileInfo acfi(cfi.absFilePath());
         readDir(&acfi,fnMap,exclSet,
-            patList,exclPatList,resultList,resultSet,errorIfNotExist,
+            patList,exclPatList,&dirResultList,resultSet,errorIfNotExist,
             recursive,killSet,paths);
       }
     }
   }
-  if (resultList)
+  if (resultList && !dirResultList.empty())
   {
     // sort the resulting list to make the order platform independent.
-    std::sort(resultList->begin(),
-              resultList->end(),
+    std::sort(dirResultList.begin(),
+              dirResultList.end(),
               [](const auto &f1,const auto &f2) { return qstricmp(f1.c_str(),f2.c_str())<0; });
+
+    // append the sorted results to resultList
+    resultList->insert(resultList->end(), dirResultList.begin(), dirResultList.end());
   }
 }
 
@@ -10157,10 +10503,10 @@ static void dumpSymbol(TextStream &t,Definition *d)
   QCString scope;
   if (d->getOuterScope() && d->getOuterScope()!=Doxygen::globalScope)
   {
-    scope = d->getOuterScope()->getOutputFileBase()+Doxygen::htmlFileExtension;
+    scope = addHtmlExtensionIfMissing(d->getOuterScope()->getOutputFileBase());
   }
   t << "REPLACE INTO symbols (symbol_id,scope_id,name,file,line) VALUES('"
-    << d->getOutputFileBase()+Doxygen::htmlFileExtension+anchor << "','"
+    << addHtmlExtensionIfMissing(d->getOutputFileBase())+anchor << "','"
     << scope << "','"
     << d->name() << "','"
     << d->getDefFileName() << "','"
@@ -10213,10 +10559,6 @@ static void version(const bool extended)
     extVers += "clang support ";
     extVers += CLANG_VERSION_STRING;
 #endif
-#if MULTITHREADED_SOURCE_GENERATOR
-    if (!extVers.isEmpty()) extVers+= ", ";
-    extVers += "multi-threaded support ";
-#endif
     if (!extVers.isEmpty())
     {
       int lastComma = extVers.findRev(',');
@@ -10266,15 +10608,15 @@ static void usage(const QCString &name,const QCString &versionString)
 
 //----------------------------------------------------------------------------
 // read the argument of option 'c' from the comment argument list and
-// update the option index 'optind'.
+// update the option index 'optInd'.
 
-static const char *getArg(int argc,char **argv,int &optind)
+static const char *getArg(int argc,char **argv,int &optInd)
 {
   char *s=0;
-  if (qstrlen(&argv[optind][2])>0)
-    s=&argv[optind][2];
-  else if (optind+1<argc && argv[optind+1][0]!='-')
-    s=argv[++optind];
+  if (qstrlen(&argv[optInd][2])>0)
+    s=&argv[optInd][2];
+  else if (optInd+1<argc && argv[optInd+1][0]!='-')
+    s=argv[++optInd];
   return s;
 }
 
@@ -10431,7 +10773,7 @@ void readConfiguration(int argc, char **argv)
    *             Handle arguments                                           *
    **************************************************************************/
 
-  int optind=1;
+  int optInd=1;
   QCString configName;
   QCString layoutName;
   QCString debugLabel;
@@ -10443,31 +10785,31 @@ void readConfiguration(int argc, char **argv)
   bool updateConfig=FALSE;
   int retVal;
   bool quiet = false;
-  while (optind<argc && argv[optind][0]=='-' &&
-               (isalpha(argv[optind][1]) || argv[optind][1]=='?' ||
-                argv[optind][1]=='-')
+  while (optInd<argc && argv[optInd][0]=='-' &&
+               (isalpha(argv[optInd][1]) || argv[optInd][1]=='?' ||
+                argv[optInd][1]=='-')
         )
   {
-    switch(argv[optind][1])
+    switch(argv[optInd][1])
     {
       case 'g':
         genConfig=TRUE;
         break;
       case 'l':
-        if (optind+1>=argc)
+        if (optInd+1>=argc)
         {
           layoutName="DoxygenLayout.xml";
         }
         else
         {
-          layoutName=argv[optind+1];
+          layoutName=argv[optInd+1];
         }
         writeDefaultLayoutFile(layoutName);
         cleanUpDoxygen();
         exit(0);
         break;
       case 'd':
-        debugLabel=getArg(argc,argv,optind);
+        debugLabel=getArg(argc,argv,optInd);
         if (debugLabel.isEmpty())
         {
           devUsage();
@@ -10493,7 +10835,7 @@ void readConfiguration(int argc, char **argv)
         updateConfig=TRUE;
         break;
       case 'e':
-        formatName=getArg(argc,argv,optind);
+        formatName=getArg(argc,argv,optInd);
         if (formatName.isEmpty())
         {
           err("option \"-e\" is missing format specifier rtf.\n");
@@ -10502,14 +10844,14 @@ void readConfiguration(int argc, char **argv)
         }
         if (qstricmp(formatName.data(),"rtf")==0)
         {
-          if (optind+1>=argc)
+          if (optInd+1>=argc)
           {
             err("option \"-e rtf\" is missing an extensions file name\n");
             cleanUpDoxygen();
             exit(1);
           }
           std::ofstream f;
-          if (openOutputFile(argv[optind+1],f))
+          if (openOutputFile(argv[optInd+1],f))
           {
             TextStream t(&f);
             RTFGenerator::writeExtensionsFile(t);
@@ -10522,7 +10864,7 @@ void readConfiguration(int argc, char **argv)
         exit(1);
         break;
       case 'f':
-        listName=getArg(argc,argv,optind);
+        listName=getArg(argc,argv,optInd);
         if (listName.isEmpty())
         {
           err("option \"-f\" is missing list specifier.\n");
@@ -10531,14 +10873,14 @@ void readConfiguration(int argc, char **argv)
         }
         if (qstricmp(listName.data(),"emoji")==0)
         {
-          if (optind+1>=argc)
+          if (optInd+1>=argc)
           {
             err("option \"-f emoji\" is missing an output file name\n");
             cleanUpDoxygen();
             exit(1);
           }
           std::ofstream f;
-          if (openOutputFile(argv[optind+1],f))
+          if (openOutputFile(argv[optInd+1],f))
           {
             TextStream t(&f);
             EmojiEntityMapper::instance()->writeEmojiFile(t);
@@ -10551,7 +10893,7 @@ void readConfiguration(int argc, char **argv)
         exit(1);
         break;
       case 'w':
-        formatName=getArg(argc,argv,optind);
+        formatName=getArg(argc,argv,optInd);
         if (formatName.isEmpty())
         {
           err("option \"-w\" is missing format specifier rtf, html or latex\n");
@@ -10560,14 +10902,14 @@ void readConfiguration(int argc, char **argv)
         }
         if (qstricmp(formatName.data(),"rtf")==0)
         {
-          if (optind+1>=argc)
+          if (optInd+1>=argc)
           {
             err("option \"-w rtf\" is missing a style sheet file name\n");
             cleanUpDoxygen();
             exit(1);
           }
           std::ofstream f;
-          if (openOutputFile(argv[optind+1],f))
+          if (openOutputFile(argv[optInd+1],f))
           {
             TextStream t(&f);
             RTFGenerator::writeStyleSheetFile(t);
@@ -10578,46 +10920,43 @@ void readConfiguration(int argc, char **argv)
         else if (qstricmp(formatName.data(),"html")==0)
         {
           Config::init();
-          if (optind+4<argc || FileInfo("Doxyfile").exists())
+          if (optInd+4<argc || FileInfo("Doxyfile").exists())
              // explicit config file mentioned or default found on disk
           {
-            QCString df = optind+4<argc ? argv[optind+4] : QCString("Doxyfile");
+            QCString df = optInd+4<argc ? argv[optInd+4] : QCString("Doxyfile");
             if (!Config::parse(df)) // parse the config file
             {
-              err("error opening or reading configuration file %s!\n",argv[optind+4]);
+              err("error opening or reading configuration file %s!\n",argv[optInd+4]);
               cleanUpDoxygen();
               exit(1);
             }
           }
-          if (optind+3>=argc)
+          if (optInd+3>=argc)
           {
             err("option \"-w html\" does not have enough arguments\n");
             cleanUpDoxygen();
             exit(1);
           }
           Config::postProcess(TRUE);
-          Config::checkAndCorrect(Config_getBool(QUIET));
+          Config::updateObsolete();
+          Config::checkAndCorrect(Config_getBool(QUIET), false);
 
-          QCString outputLanguage=Config_getEnum(OUTPUT_LANGUAGE);
-          if (!setTranslator(outputLanguage))
-          {
-            warn_uncond("Output language %s not supported! Using English instead.\n", qPrint(outputLanguage));
-          }
+          setTranslator(Config_getEnum(OUTPUT_LANGUAGE));
 
           std::ofstream f;
-          if (openOutputFile(argv[optind+1],f))
+          if (openOutputFile(argv[optInd+1],f))
           {
             TextStream t(&f);
-            HtmlGenerator::writeHeaderFile(t, argv[optind+3]);
+            HtmlGenerator::writeHeaderFile(t, argv[optInd+3]);
           }
           f.close();
-          if (openOutputFile(argv[optind+2],f))
+          if (openOutputFile(argv[optInd+2],f))
           {
             TextStream t(&f);
             HtmlGenerator::writeFooterFile(t);
           }
           f.close();
-          if (openOutputFile(argv[optind+3],f))
+          if (openOutputFile(argv[optInd+3],f))
           {
             TextStream t(&f);
             HtmlGenerator::writeStyleSheetFile(t);
@@ -10628,45 +10967,42 @@ void readConfiguration(int argc, char **argv)
         else if (qstricmp(formatName.data(),"latex")==0)
         {
           Config::init();
-          if (optind+4<argc || FileInfo("Doxyfile").exists())
+          if (optInd+4<argc || FileInfo("Doxyfile").exists())
           {
-            QCString df = optind+4<argc ? argv[optind+4] : QCString("Doxyfile");
+            QCString df = optInd+4<argc ? argv[optInd+4] : QCString("Doxyfile");
             if (!Config::parse(df))
             {
-              err("error opening or reading configuration file %s!\n",argv[optind+4]);
+              err("error opening or reading configuration file %s!\n",argv[optInd+4]);
               cleanUpDoxygen();
               exit(1);
             }
           }
-          if (optind+3>=argc)
+          if (optInd+3>=argc)
           {
             err("option \"-w latex\" does not have enough arguments\n");
             cleanUpDoxygen();
             exit(1);
           }
           Config::postProcess(TRUE);
-          Config::checkAndCorrect(Config_getBool(QUIET));
+          Config::updateObsolete();
+          Config::checkAndCorrect(Config_getBool(QUIET), false);
 
-          QCString outputLanguage=Config_getEnum(OUTPUT_LANGUAGE);
-          if (!setTranslator(outputLanguage))
-          {
-            warn_uncond("Output language %s not supported! Using English instead.\n", qPrint(outputLanguage));
-          }
+          setTranslator(Config_getEnum(OUTPUT_LANGUAGE));
 
           std::ofstream f;
-          if (openOutputFile(argv[optind+1],f))
+          if (openOutputFile(argv[optInd+1],f))
           {
             TextStream t(&f);
             LatexGenerator::writeHeaderFile(t);
           }
           f.close();
-          if (openOutputFile(argv[optind+2],f))
+          if (openOutputFile(argv[optInd+2],f))
           {
             TextStream t(&f);
             LatexGenerator::writeFooterFile(t);
           }
           f.close();
-          if (openOutputFile(argv[optind+3],f))
+          if (openOutputFile(argv[optInd+3],f))
           {
             TextStream t(&f);
             LatexGenerator::writeStyleSheetFile(t);
@@ -10695,19 +11031,19 @@ void readConfiguration(int argc, char **argv)
         exit(0);
         break;
       case '-':
-        if (qstrcmp(&argv[optind][2],"help")==0)
+        if (qstrcmp(&argv[optInd][2],"help")==0)
         {
           usage(argv[0],versionString);
           exit(0);
         }
-        else if (qstrcmp(&argv[optind][2],"version")==0)
+        else if (qstrcmp(&argv[optInd][2],"version")==0)
         {
           version(false);
           cleanUpDoxygen();
           exit(0);
         }
-        else if ((qstrcmp(&argv[optind][2],"Version")==0) ||
-                 (qstrcmp(&argv[optind][2],"VERSION")==0))
+        else if ((qstrcmp(&argv[optInd][2],"Version")==0) ||
+                 (qstrcmp(&argv[optInd][2],"VERSION")==0))
         {
           version(true);
           cleanUpDoxygen();
@@ -10715,7 +11051,7 @@ void readConfiguration(int argc, char **argv)
         }
         else
         {
-          err("Unknown option \"-%s\"\n",&argv[optind][1]);
+          err("Unknown option \"-%s\"\n",&argv[optInd][1]);
           usage(argv[0],versionString);
           exit(1);
         }
@@ -10738,11 +11074,11 @@ void readConfiguration(int argc, char **argv)
         exit(0);
         break;
       default:
-        err("Unknown option \"-%c\"\n",argv[optind][1]);
+        err("Unknown option \"-%c\"\n",argv[optInd][1]);
         usage(argv[0],versionString);
         exit(1);
     }
-    optind++;
+    optInd++;
   }
 
   /**************************************************************************
@@ -10752,7 +11088,7 @@ void readConfiguration(int argc, char **argv)
   Config::init();
 
   FileInfo configFileInfo1("Doxyfile"),configFileInfo2("doxyfile");
-  if (optind>=argc)
+  if (optInd>=argc)
   {
     if (configFileInfo1.exists())
     {
@@ -10775,14 +11111,14 @@ void readConfiguration(int argc, char **argv)
   }
   else
   {
-    FileInfo fi(argv[optind]);
-    if (fi.exists() || qstrcmp(argv[optind],"-")==0 || genConfig)
+    FileInfo fi(argv[optInd]);
+    if (fi.exists() || qstrcmp(argv[optInd],"-")==0 || genConfig)
     {
-      configName=argv[optind];
+      configName=argv[optInd];
     }
     else
     {
-      err("configuration file %s not found!\n",argv[optind]);
+      err("configuration file %s not found!\n",argv[optInd]);
       usage(argv[0],versionString);
       exit(1);
     }
@@ -10811,6 +11147,7 @@ void readConfiguration(int argc, char **argv)
 
   if (diffList)
   {
+    Config::updateObsolete();
     compareDoxyfile();
     cleanUpDoxygen();
     exit(0);
@@ -10818,6 +11155,7 @@ void readConfiguration(int argc, char **argv)
 
   if (updateConfig)
   {
+    Config::updateObsolete();
     generateConfigFile(configName,shortList,TRUE);
     cleanUpDoxygen();
     exit(0);
@@ -10836,7 +11174,8 @@ void checkConfiguration()
 {
 
   Config::postProcess(FALSE);
-  Config::checkAndCorrect(Config_getBool(QUIET));
+  Config::updateObsolete();
+  Config::checkAndCorrect(Config_getBool(QUIET), true);
   initWarningFormat();
 }
 
@@ -10852,12 +11191,7 @@ void adjustConfiguration()
   Doxygen::mscFileNameLinkedMap = new FileNameLinkedMap;
   Doxygen::diaFileNameLinkedMap = new FileNameLinkedMap;
 
-  QCString outputLanguage=Config_getEnum(OUTPUT_LANGUAGE);
-  if (!setTranslator(outputLanguage))
-  {
-    warn_uncond("Output language %s not supported! Using English instead.\n",
-       qPrint(outputLanguage));
-  }
+  setTranslator(Config_getEnum(OUTPUT_LANGUAGE));
 
   /* Set the global html file extension. */
   Doxygen::htmlFileExtension = Config_getString(HTML_FILE_EXTENSION);
@@ -10924,6 +11258,7 @@ void adjustConfiguration()
 #ifdef HAS_SIGNALS
 static void stopDoxygen(int)
 {
+  signal(SIGINT,SIG_DFL);   // Re-register signal handler for default action
   Dir thisDir;
   msg("Cleaning up...\n");
   if (!Doxygen::filterDBFileName.isEmpty())
@@ -11323,6 +11658,19 @@ void parseInput()
   {
     htmlOutput = createOutputDirectory(outputDirectory,Config_getString(HTML_OUTPUT),"/html");
     Config_updateString(HTML_OUTPUT,htmlOutput);
+
+    // add HTML indexers that are enabled
+    bool generateHtmlHelp    = Config_getBool(GENERATE_HTMLHELP);
+    bool generateEclipseHelp = Config_getBool(GENERATE_ECLIPSEHELP);
+    bool generateQhp         = Config_getBool(GENERATE_QHP);
+    bool generateTreeView    = Config_getBool(GENERATE_TREEVIEW);
+    bool generateDocSet      = Config_getBool(GENERATE_DOCSET);
+    if (generateEclipseHelp) Doxygen::indexList->addIndex<EclipseHelp>();
+    if (generateHtmlHelp)    Doxygen::indexList->addIndex<HtmlHelp>();
+    if (generateQhp)         Doxygen::indexList->addIndex<Qhp>();
+    if (generateTreeView)    Doxygen::indexList->addIndex<FTVHelp>(TRUE);
+    if (generateDocSet)      Doxygen::indexList->addIndex<DocSets>();
+    Doxygen::indexList->initialize();
   }
 
   QCString docbookOutput;
@@ -11547,6 +11895,7 @@ void parseInput()
 
   g_s.begin("Associating documentation with concepts...\n");
   buildConceptDocList(root.get());
+  distributeConceptGroups();
   g_s.end();
 
   g_s.begin("Building example list...\n");
@@ -11821,6 +12170,7 @@ void parseInput()
 
   g_s.begin("Adding members to index pages...\n");
   addMembersToIndex();
+  addToIndices();
   g_s.end();
 
   g_s.begin("Correcting members for VHDL...\n");
@@ -11876,19 +12226,6 @@ void generateOutput()
   {
     g_outputList->add<HtmlGenerator>();
     HtmlGenerator::init();
-
-    // add HTML indexers that are enabled
-    bool generateHtmlHelp    = Config_getBool(GENERATE_HTMLHELP);
-    bool generateEclipseHelp = Config_getBool(GENERATE_ECLIPSEHELP);
-    bool generateQhp         = Config_getBool(GENERATE_QHP);
-    bool generateTreeView    = Config_getBool(GENERATE_TREEVIEW);
-    bool generateDocSet      = Config_getBool(GENERATE_DOCSET);
-    if (generateEclipseHelp) Doxygen::indexList->addIndex<EclipseHelp>();
-    if (generateHtmlHelp)    Doxygen::indexList->addIndex<HtmlHelp>();
-    if (generateQhp)         Doxygen::indexList->addIndex<Qhp>();
-    if (generateTreeView)    Doxygen::indexList->addIndex<FTVHelp>(TRUE);
-    if (generateDocSet)      Doxygen::indexList->addIndex<DocSets>();
-    Doxygen::indexList->initialize();
     HtmlGenerator::writeTabData();
   }
   if (generateLatex)
@@ -11959,12 +12296,35 @@ void generateOutput()
   }
   g_s.end();
 
+  // copy static stuff
+  if (generateHtml)
+  {
+    FTVHelp::generateTreeViewImages();
+    copyStyleSheet();
+    copyLogo(Config_getString(HTML_OUTPUT));
+    copyExtraFiles(Config_getList(HTML_EXTRA_FILES),"HTML_EXTRA_FILES",Config_getString(HTML_OUTPUT));
+  }
+  if (generateLatex)
+  {
+    copyLatexStyleSheet();
+    copyLogo(Config_getString(LATEX_OUTPUT));
+    copyExtraFiles(Config_getList(LATEX_EXTRA_FILES),"LATEX_EXTRA_FILES",Config_getString(LATEX_OUTPUT));
+  }
+  if (generateDocbook)
+  {
+    copyLogo(Config_getString(DOCBOOK_OUTPUT));
+  }
+  if (generateRtf)
+  {
+    copyLogo(Config_getString(RTF_OUTPUT));
+  }
+
   const FormulaManager &fm = FormulaManager::instance();
   if (fm.hasFormulas() && generateHtml
       && !Config_getBool(USE_MATHJAX))
   {
     g_s.begin("Generating images for formulas in HTML...\n");
-    fm.generateImages(Config_getString(HTML_OUTPUT), Config_getEnum(HTML_FORMULA_FORMAT)=="svg" ?
+    fm.generateImages(Config_getString(HTML_OUTPUT), Config_getEnum(HTML_FORMULA_FORMAT)==HTML_FORMULA_FORMAT_t::svg ?
         FormulaManager::Format::Vector : FormulaManager::Format::Bitmap, FormulaManager::HighDPI::On);
     g_s.end();
   }
@@ -12094,7 +12454,12 @@ void generateOutput()
     g_s.end();
   }
 
-  if (g_useOutputTemplate) generateOutputViaTemplate();
+  if (g_useOutputTemplate)
+  {
+    g_s.begin("Generating output via template engine...\n");
+    generateOutputViaTemplate();
+    g_s.end();
+  }
 
   warn_flush();
 
@@ -12123,29 +12488,6 @@ void generateOutput()
     g_s.end();
   }
 
-  // copy static stuff
-  if (generateHtml)
-  {
-    FTVHelp::generateTreeViewImages();
-    copyStyleSheet();
-    copyLogo(Config_getString(HTML_OUTPUT));
-    copyExtraFiles(Config_getList(HTML_EXTRA_FILES),"HTML_EXTRA_FILES",Config_getString(HTML_OUTPUT));
-  }
-  if (generateLatex)
-  {
-    copyLatexStyleSheet();
-    copyLogo(Config_getString(LATEX_OUTPUT));
-    copyExtraFiles(Config_getList(LATEX_EXTRA_FILES),"LATEX_EXTRA_FILES",Config_getString(LATEX_OUTPUT));
-  }
-  if (generateDocbook)
-  {
-    copyLogo(Config_getString(DOCBOOK_OUTPUT));
-  }
-  if (generateRtf)
-  {
-    copyLogo(Config_getString(RTF_OUTPUT));
-  }
-
   if (generateHtml &&
       Config_getBool(GENERATE_HTMLHELP) &&
       !Config_getString(HHC_LOCATION).isEmpty())
diff --git a/src/doxygen_lex.h b/src/doxygen_lex.h
new file mode 100644 (file)
index 0000000..bb61660
--- /dev/null
@@ -0,0 +1,56 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2021 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 DOXYGEN_LEX_H
+#define DOXYGEN_LEX_H
+
+#ifndef LEX_NO_REENTRANT
+#ifndef LEX_NO_INPUT_FILENAME
+#define YY_FATAL_ERROR(msg)                                          \
+{                                                                    \
+  QCString msg1 = msg;                                               \
+  msg1 += "\n    lexical analyzer: ";                                \
+  msg1 += getLexerFILE();                                            \
+  if (!((struct yyguts_t*)yyscanner)->yyextra_r->fileName.isEmpty()) \
+  {                                                                  \
+    msg1 += " (for: ";                                               \
+    msg1 += ((struct yyguts_t*)yyscanner)->yyextra_r->fileName;      \
+    msg1 += ")";                                                     \
+  }                                                                  \
+  msg1 += "\n";                                                      \
+  yy_fatal_error( qPrint(msg1) , yyscanner);                         \
+}
+#else
+#define YY_FATAL_ERROR(msg)                                          \
+{                                                                    \
+  QCString msg1 = msg;                                               \
+  msg1 += "\n    lexical analyzer: ";                                \
+  msg1 += getLexerFILE();                                            \
+  msg1 += "\n";                                                      \
+  yy_fatal_error( qPrint(msg1) , yyscanner);                         \
+}
+#endif
+#else
+#define YY_FATAL_ERROR(msg)                                          \
+{                                                                    \
+  QCString msg1 = msg;                                               \
+  msg1 += "\n    lexical analyzer: ";                                \
+  msg1 += getLexerFILE();                                            \
+  msg1 += "\n";                                                      \
+  yy_fatal_error( qPrint(msg1));                                     \
+}
+#endif
+
+#endif
index b2f8193..53a370b 100644 (file)
@@ -188,7 +188,7 @@ void EclipseHelp::addContentsItem(
         indent();
         m_tocstream << "<topic label=\"" << convertToXML(name) << "\"";
         m_tocstream << " href=\"" << convertToXML(m_pathprefix)
-                    << file << Doxygen::htmlFileExtension;
+                    << addHtmlExtensionIfMissing(file);
         if (!anchor.isEmpty())
         {
           m_tocstream << "#" << anchor;
index d723f64..750ec16 100644 (file)
@@ -35,9 +35,13 @@ static struct emojiEntityInfo
   { ":8ball:",                                 "&#x1f3b1;"                            },
   { ":a:",                                     "&#x1f170;"                            },
   { ":ab:",                                    "&#x1f18e;"                            },
+  { ":abacus:",                                "&#x1f9ee;"                            },
   { ":abc:",                                   "&#x1f524;"                            },
   { ":abcd:",                                  "&#x1f521;"                            },
   { ":accept:",                                "&#x1f251;"                            },
+  { ":accordion:",                             "&#x1fa97;"                            },
+  { ":adhesive_bandage:",                      "&#x1fa79;"                            },
+  { ":adult:",                                 "&#x1f9d1;"                            },
   { ":aerial_tramway:",                        "&#x1f6a1;"                            },
   { ":afghanistan:",                           "&#x1f1e6;&#x1f1eb;"                   },
   { ":airplane:",                              "&#x2708;"                             },
@@ -50,6 +54,7 @@ static struct emojiEntityInfo
   { ":ambulance:",                             "&#x1f691;"                            },
   { ":american_samoa:",                        "&#x1f1e6;&#x1f1f8;"                   },
   { ":amphora:",                               "&#x1f3fa;"                            },
+  { ":anatomical_heart:",                      "&#x1fac0;"                            },
   { ":anchor:",                                "&#x2693;"                             },
   { ":andorra:",                               "&#x1f1e6;&#x1f1e9;"                   },
   { ":angel:",                                 "&#x1f47c;"                            },
@@ -89,15 +94,20 @@ static struct emojiEntityInfo
   { ":art:",                                   "&#x1f3a8;"                            },
   { ":articulated_lorry:",                     "&#x1f69b;"                            },
   { ":artificial_satellite:",                  "&#x1f6f0;"                            },
+  { ":artist:",                                "&#x1f9d1;&#x200d;&#x1f3a8;"           },
   { ":aruba:",                                 "&#x1f1e6;&#x1f1fc;"                   },
-  { ":asterisk:",                              "&#x002a;&#x20e3;"                     },
+  { ":ascension_island:",                      "&#x1f1e6;&#x1f1e8;"                   },
+  { ":asterisk:",                              "&#x002a;&#xfe0f;&#x20e3;"             },
   { ":astonished:",                            "&#x1f632;"                            },
+  { ":astronaut:",                             "&#x1f9d1;&#x200d;&#x1f680;"           },
   { ":athletic_shoe:",                         "&#x1f45f;"                            },
   { ":atm:",                                   "&#x1f3e7;"                            },
   { ":atom_symbol:",                           "&#x269b;"                             },
   { ":australia:",                             "&#x1f1e6;&#x1f1fa;"                   },
   { ":austria:",                               "&#x1f1e6;&#x1f1f9;"                   },
+  { ":auto_rickshaw:",                         "&#x1f6fa;"                            },
   { ":avocado:",                               "&#x1f951;"                            },
+  { ":axe:",                                   "&#x1fa93;"                            },
   { ":azerbaijan:",                            "&#x1f1e6;&#x1f1ff;"                   },
   { ":b:",                                     "&#x1f171;"                            },
   { ":baby:",                                  "&#x1f476;"                            },
@@ -106,12 +116,17 @@ static struct emojiEntityInfo
   { ":baby_symbol:",                           "&#x1f6bc;"                            },
   { ":back:",                                  "&#x1f519;"                            },
   { ":bacon:",                                 "&#x1f953;"                            },
+  { ":badger:",                                "&#x1f9a1;"                            },
   { ":badminton:",                             "&#x1f3f8;"                            },
+  { ":bagel:",                                 "&#x1f96f;"                            },
   { ":baggage_claim:",                         "&#x1f6c4;"                            },
   { ":baguette_bread:",                        "&#x1f956;"                            },
   { ":bahamas:",                               "&#x1f1e7;&#x1f1f8;"                   },
   { ":bahrain:",                               "&#x1f1e7;&#x1f1ed;"                   },
   { ":balance_scale:",                         "&#x2696;"                             },
+  { ":bald_man:",                              "&#x1f468;&#x200d;&#x1f9b2;"           },
+  { ":bald_woman:",                            "&#x1f469;&#x200d;&#x1f9b2;"           },
+  { ":ballet_shoes:",                          "&#x1fa70;"                            },
   { ":balloon:",                               "&#x1f388;"                            },
   { ":ballot_box:",                            "&#x1f5f3;"                            },
   { ":ballot_box_with_check:",                 "&#x2611;"                             },
@@ -119,43 +134,52 @@ static struct emojiEntityInfo
   { ":banana:",                                "&#x1f34c;"                            },
   { ":bangbang:",                              "&#x203c;"                             },
   { ":bangladesh:",                            "&#x1f1e7;&#x1f1e9;"                   },
+  { ":banjo:",                                 "&#x1fa95;"                            },
   { ":bank:",                                  "&#x1f3e6;"                            },
   { ":bar_chart:",                             "&#x1f4ca;"                            },
   { ":barbados:",                              "&#x1f1e7;&#x1f1e7;"                   },
   { ":barber:",                                "&#x1f488;"                            },
   { ":baseball:",                              "&#x26be;"                             },
+  { ":basket:",                                "&#x1f9fa;"                            },
   { ":basketball:",                            "&#x1f3c0;"                            },
-  { ":basketball_man:",                        "&#x26f9;"                             },
-  { ":basketball_woman:",                      "&#x26f9;&#x2640;"                     },
+  { ":basketball_man:",                        "&#x26f9;&#xfe0f;&#x200d;&#x2642;&#xfe0f;" },
+  { ":basketball_woman:",                      "&#x26f9;&#xfe0f;&#x200d;&#x2640;&#xfe0f;" },
   { ":bat:",                                   "&#x1f987;"                            },
   { ":bath:",                                  "&#x1f6c0;"                            },
   { ":bathtub:",                               "&#x1f6c1;"                            },
   { ":battery:",                               "&#x1f50b;"                            },
   { ":beach_umbrella:",                        "&#x1f3d6;"                            },
   { ":bear:",                                  "&#x1f43b;"                            },
+  { ":bearded_person:",                        "&#x1f9d4;"                            },
+  { ":beaver:",                                "&#x1f9ab;"                            },
   { ":bed:",                                   "&#x1f6cf;"                            },
   { ":bee:",                                   "&#x1f41d;"                            },
   { ":beer:",                                  "&#x1f37a;"                            },
   { ":beers:",                                 "&#x1f37b;"                            },
-  { ":beetle:",                                "&#x1f41e;"                            },
+  { ":beetle:",                                "&#x1fab2;"                            },
   { ":beginner:",                              "&#x1f530;"                            },
   { ":belarus:",                               "&#x1f1e7;&#x1f1fe;"                   },
   { ":belgium:",                               "&#x1f1e7;&#x1f1ea;"                   },
   { ":belize:",                                "&#x1f1e7;&#x1f1ff;"                   },
   { ":bell:",                                  "&#x1f514;"                            },
+  { ":bell_pepper:",                           "&#x1fad1;"                            },
   { ":bellhop_bell:",                          "&#x1f6ce;"                            },
   { ":benin:",                                 "&#x1f1e7;&#x1f1ef;"                   },
   { ":bento:",                                 "&#x1f371;"                            },
   { ":bermuda:",                               "&#x1f1e7;&#x1f1f2;"                   },
+  { ":beverage_box:",                          "&#x1f9c3;"                            },
   { ":bhutan:",                                "&#x1f1e7;&#x1f1f9;"                   },
   { ":bicyclist:",                             "&#x1f6b4;"                            },
   { ":bike:",                                  "&#x1f6b2;"                            },
-  { ":biking_man:",                            "&#x1f6b4;"                            },
-  { ":biking_woman:",                          "&#x1f6b4;&#x2640;"                    },
+  { ":biking_man:",                            "&#x1f6b4;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":biking_woman:",                          "&#x1f6b4;&#x200d;&#x2640;&#xfe0f;"    },
   { ":bikini:",                                "&#x1f459;"                            },
+  { ":billed_cap:",                            "&#x1f9e2;"                            },
   { ":biohazard:",                             "&#x2623;"                             },
   { ":bird:",                                  "&#x1f426;"                            },
   { ":birthday:",                              "&#x1f382;"                            },
+  { ":bison:",                                 "&#x1f9ac;"                            },
+  { ":black_cat:",                             "&#x1f408;&#x200d;&#x2b1b;"            },
   { ":black_circle:",                          "&#x26ab;"                             },
   { ":black_flag:",                            "&#x1f3f4;"                            },
   { ":black_heart:",                           "&#x1f5a4;"                            },
@@ -166,43 +190,64 @@ static struct emojiEntityInfo
   { ":black_nib:",                             "&#x2712;"                             },
   { ":black_small_square:",                    "&#x25aa;"                             },
   { ":black_square_button:",                   "&#x1f532;"                            },
-  { ":blonde_man:",                            "&#x1f471;"                            },
-  { ":blonde_woman:",                          "&#x1f471;&#x2640;"                    },
+  { ":blond_haired_man:",                      "&#x1f471;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":blond_haired_person:",                   "&#x1f471;"                            },
+  { ":blond_haired_woman:",                    "&#x1f471;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":blonde_woman:",                          "&#x1f471;&#x200d;&#x2640;&#xfe0f;"    },
   { ":blossom:",                               "&#x1f33c;"                            },
   { ":blowfish:",                              "&#x1f421;"                            },
   { ":blue_book:",                             "&#x1f4d8;"                            },
   { ":blue_car:",                              "&#x1f699;"                            },
   { ":blue_heart:",                            "&#x1f499;"                            },
+  { ":blue_square:",                           "&#x1f7e6;"                            },
+  { ":blueberries:",                           "&#x1fad0;"                            },
   { ":blush:",                                 "&#x1f60a;"                            },
   { ":boar:",                                  "&#x1f417;"                            },
   { ":boat:",                                  "&#x26f5;"                             },
   { ":bolivia:",                               "&#x1f1e7;&#x1f1f4;"                   },
   { ":bomb:",                                  "&#x1f4a3;"                            },
+  { ":bone:",                                  "&#x1f9b4;"                            },
   { ":book:",                                  "&#x1f4d6;"                            },
   { ":bookmark:",                              "&#x1f516;"                            },
   { ":bookmark_tabs:",                         "&#x1f4d1;"                            },
   { ":books:",                                 "&#x1f4da;"                            },
   { ":boom:",                                  "&#x1f4a5;"                            },
+  { ":boomerang:",                             "&#x1fa83;"                            },
   { ":boot:",                                  "&#x1f462;"                            },
   { ":bosnia_herzegovina:",                    "&#x1f1e7;&#x1f1e6;"                   },
   { ":botswana:",                              "&#x1f1e7;&#x1f1fc;"                   },
+  { ":bouncing_ball_man:",                     "&#x26f9;&#xfe0f;&#x200d;&#x2642;&#xfe0f;" },
+  { ":bouncing_ball_person:",                  "&#x26f9;"                             },
+  { ":bouncing_ball_woman:",                   "&#x26f9;&#xfe0f;&#x200d;&#x2640;&#xfe0f;" },
   { ":bouquet:",                               "&#x1f490;"                            },
+  { ":bouvet_island:",                         "&#x1f1e7;&#x1f1fb;"                   },
   { ":bow:",                                   "&#x1f647;"                            },
   { ":bow_and_arrow:",                         "&#x1f3f9;"                            },
-  { ":bowing_man:",                            "&#x1f647;"                            },
-  { ":bowing_woman:",                          "&#x1f647;&#x2640;"                    },
+  { ":bowing_man:",                            "&#x1f647;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":bowing_woman:",                          "&#x1f647;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":bowl_with_spoon:",                       "&#x1f963;"                            },
   { ":bowling:",                               "&#x1f3b3;"                            },
   { ":boxing_glove:",                          "&#x1f94a;"                            },
   { ":boy:",                                   "&#x1f466;"                            },
+  { ":brain:",                                 "&#x1f9e0;"                            },
   { ":brazil:",                                "&#x1f1e7;&#x1f1f7;"                   },
   { ":bread:",                                 "&#x1f35e;"                            },
-  { ":bride_with_veil:",                       "&#x1f470;"                            },
+  { ":breast_feeding:",                        "&#x1f931;"                            },
+  { ":bricks:",                                "&#x1f9f1;"                            },
+  { ":bride_with_veil:",                       "&#x1f470;&#x200d;&#x2640;&#xfe0f;"    },
   { ":bridge_at_night:",                       "&#x1f309;"                            },
   { ":briefcase:",                             "&#x1f4bc;"                            },
   { ":british_indian_ocean_territory:",        "&#x1f1ee;&#x1f1f4;"                   },
   { ":british_virgin_islands:",                "&#x1f1fb;&#x1f1ec;"                   },
+  { ":broccoli:",                              "&#x1f966;"                            },
   { ":broken_heart:",                          "&#x1f494;"                            },
+  { ":broom:",                                 "&#x1f9f9;"                            },
+  { ":brown_circle:",                          "&#x1f7e4;"                            },
+  { ":brown_heart:",                           "&#x1f90e;"                            },
+  { ":brown_square:",                          "&#x1f7eb;"                            },
   { ":brunei:",                                "&#x1f1e7;&#x1f1f3;"                   },
+  { ":bubble_tea:",                            "&#x1f9cb;"                            },
+  { ":bucket:",                                "&#x1faa3;"                            },
   { ":bug:",                                   "&#x1f41b;"                            },
   { ":building_construction:",                 "&#x1f3d7;"                            },
   { ":bulb:",                                  "&#x1f4a1;"                            },
@@ -217,6 +262,7 @@ static struct emojiEntityInfo
   { ":busstop:",                               "&#x1f68f;"                            },
   { ":bust_in_silhouette:",                    "&#x1f464;"                            },
   { ":busts_in_silhouette:",                   "&#x1f465;"                            },
+  { ":butter:",                                "&#x1f9c8;"                            },
   { ":butterfly:",                             "&#x1f98b;"                            },
   { ":cactus:",                                "&#x1f335;"                            },
   { ":cake:",                                  "&#x1f370;"                            },
@@ -234,6 +280,7 @@ static struct emojiEntityInfo
   { ":cancer:",                                "&#x264b;"                             },
   { ":candle:",                                "&#x1f56f;"                            },
   { ":candy:",                                 "&#x1f36c;"                            },
+  { ":canned_food:",                           "&#x1f96b;"                            },
   { ":canoe:",                                 "&#x1f6f6;"                            },
   { ":cape_verde:",                            "&#x1f1e8;&#x1f1fb;"                   },
   { ":capital_abcd:",                          "&#x1f520;"                            },
@@ -244,14 +291,18 @@ static struct emojiEntityInfo
   { ":card_index_dividers:",                   "&#x1f5c2;"                            },
   { ":caribbean_netherlands:",                 "&#x1f1e7;&#x1f1f6;"                   },
   { ":carousel_horse:",                        "&#x1f3a0;"                            },
+  { ":carpentry_saw:",                         "&#x1fa9a;"                            },
   { ":carrot:",                                "&#x1f955;"                            },
+  { ":cartwheeling:",                          "&#x1f938;"                            },
   { ":cat:",                                   "&#x1f431;"                            },
   { ":cat2:",                                  "&#x1f408;"                            },
   { ":cayman_islands:",                        "&#x1f1f0;&#x1f1fe;"                   },
   { ":cd:",                                    "&#x1f4bf;"                            },
   { ":central_african_republic:",              "&#x1f1e8;&#x1f1eb;"                   },
+  { ":ceuta_melilla:",                         "&#x1f1ea;&#x1f1e6;"                   },
   { ":chad:",                                  "&#x1f1f9;&#x1f1e9;"                   },
   { ":chains:",                                "&#x26d3;"                             },
+  { ":chair:",                                 "&#x1fa91;"                            },
   { ":champagne:",                             "&#x1f37e;"                            },
   { ":chart:",                                 "&#x1f4b9;"                            },
   { ":chart_with_downwards_trend:",            "&#x1f4c9;"                            },
@@ -260,12 +311,15 @@ static struct emojiEntityInfo
   { ":cheese:",                                "&#x1f9c0;"                            },
   { ":cherries:",                              "&#x1f352;"                            },
   { ":cherry_blossom:",                        "&#x1f338;"                            },
+  { ":chess_pawn:",                            "&#x265f;"                             },
   { ":chestnut:",                              "&#x1f330;"                            },
   { ":chicken:",                               "&#x1f414;"                            },
+  { ":child:",                                 "&#x1f9d2;"                            },
   { ":children_crossing:",                     "&#x1f6b8;"                            },
   { ":chile:",                                 "&#x1f1e8;&#x1f1f1;"                   },
   { ":chipmunk:",                              "&#x1f43f;"                            },
   { ":chocolate_bar:",                         "&#x1f36b;"                            },
+  { ":chopsticks:",                            "&#x1f962;"                            },
   { ":christmas_island:",                      "&#x1f1e8;&#x1f1fd;"                   },
   { ":christmas_tree:",                        "&#x1f384;"                            },
   { ":church:",                                "&#x26ea;"                             },
@@ -279,8 +333,12 @@ static struct emojiEntityInfo
   { ":clap:",                                  "&#x1f44f;"                            },
   { ":clapper:",                               "&#x1f3ac;"                            },
   { ":classical_building:",                    "&#x1f3db;"                            },
+  { ":climbing:",                              "&#x1f9d7;"                            },
+  { ":climbing_man:",                          "&#x1f9d7;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":climbing_woman:",                        "&#x1f9d7;&#x200d;&#x2640;&#xfe0f;"    },
   { ":clinking_glasses:",                      "&#x1f942;"                            },
   { ":clipboard:",                             "&#x1f4cb;"                            },
+  { ":clipperton_island:",                     "&#x1f1e8;&#x1f1f5;"                   },
   { ":clock1:",                                "&#x1f550;"                            },
   { ":clock10:",                               "&#x1f559;"                            },
   { ":clock1030:",                             "&#x1f565;"                            },
@@ -316,15 +374,21 @@ static struct emojiEntityInfo
   { ":clown_face:",                            "&#x1f921;"                            },
   { ":clubs:",                                 "&#x2663;"                             },
   { ":cn:",                                    "&#x1f1e8;&#x1f1f3;"                   },
+  { ":coat:",                                  "&#x1f9e5;"                            },
+  { ":cockroach:",                             "&#x1fab3;"                            },
   { ":cocktail:",                              "&#x1f378;"                            },
+  { ":coconut:",                               "&#x1f965;"                            },
   { ":cocos_islands:",                         "&#x1f1e8;&#x1f1e8;"                   },
   { ":coffee:",                                "&#x2615;"                             },
   { ":coffin:",                                "&#x26b0;"                             },
+  { ":coin:",                                  "&#x1fa99;"                            },
+  { ":cold_face:",                             "&#x1f976;"                            },
   { ":cold_sweat:",                            "&#x1f630;"                            },
   { ":collision:",                             "&#x1f4a5;"                            },
   { ":colombia:",                              "&#x1f1e8;&#x1f1f4;"                   },
   { ":comet:",                                 "&#x2604;"                             },
   { ":comoros:",                               "&#x1f1f0;&#x1f1f2;"                   },
+  { ":compass:",                               "&#x1f9ed;"                            },
   { ":computer:",                              "&#x1f4bb;"                            },
   { ":computer_mouse:",                        "&#x1f5b1;"                            },
   { ":confetti_ball:",                         "&#x1f38a;"                            },
@@ -335,10 +399,11 @@ static struct emojiEntityInfo
   { ":congratulations:",                       "&#x3297;"                             },
   { ":construction:",                          "&#x1f6a7;"                            },
   { ":construction_worker:",                   "&#x1f477;"                            },
-  { ":construction_worker_man:",               "&#x1f477;"                            },
-  { ":construction_worker_woman:",             "&#x1f477;&#x2640;"                    },
+  { ":construction_worker_man:",               "&#x1f477;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":construction_worker_woman:",             "&#x1f477;&#x200d;&#x2640;&#xfe0f;"    },
   { ":control_knobs:",                         "&#x1f39b;"                            },
   { ":convenience_store:",                     "&#x1f3ea;"                            },
+  { ":cook:",                                  "&#x1f9d1;&#x200d;&#x1f373;"           },
   { ":cook_islands:",                          "&#x1f1e8;&#x1f1f0;"                   },
   { ":cookie:",                                "&#x1f36a;"                            },
   { ":cool:",                                  "&#x1f192;"                            },
@@ -350,12 +415,13 @@ static struct emojiEntityInfo
   { ":couch_and_lamp:",                        "&#x1f6cb;"                            },
   { ":couple:",                                "&#x1f46b;"                            },
   { ":couple_with_heart:",                     "&#x1f491;"                            },
-  { ":couple_with_heart_man_man:",             "&#x1f468;&#x2764;&#x1f468;"           },
-  { ":couple_with_heart_woman_man:",           "&#x1f491;"                            },
-  { ":couple_with_heart_woman_woman:",         "&#x1f469;&#x2764;&#x1f469;"           },
-  { ":couplekiss_man_man:",                    "&#x1f468;&#x2764;&#x1f48b;&#x1f468;"  },
-  { ":couplekiss_man_woman:",                  "&#x1f48f;"                            },
-  { ":couplekiss_woman_woman:",                "&#x1f469;&#x2764;&#x1f48b;&#x1f469;"  },
+  { ":couple_with_heart_man_man:",             "&#x1f468;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f468;" },
+  { ":couple_with_heart_woman_man:",           "&#x1f469;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f468;" },
+  { ":couple_with_heart_woman_woman:",         "&#x1f469;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f469;" },
+  { ":couplekiss:",                            "&#x1f48f;"                            },
+  { ":couplekiss_man_man:",                    "&#x1f468;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f468;" },
+  { ":couplekiss_man_woman:",                  "&#x1f469;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f468;" },
+  { ":couplekiss_woman_woman:",                "&#x1f469;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f469;" },
   { ":cow:",                                   "&#x1f42e;"                            },
   { ":cow2:",                                  "&#x1f404;"                            },
   { ":cowboy_hat_face:",                       "&#x1f920;"                            },
@@ -363,7 +429,8 @@ static struct emojiEntityInfo
   { ":crayon:",                                "&#x1f58d;"                            },
   { ":credit_card:",                           "&#x1f4b3;"                            },
   { ":crescent_moon:",                         "&#x1f319;"                            },
-  { ":cricket:",                               "&#x1f3cf;"                            },
+  { ":cricket:",                               "&#x1f997;"                            },
+  { ":cricket_game:",                          "&#x1f3cf;"                            },
   { ":croatia:",                               "&#x1f1ed;&#x1f1f7;"                   },
   { ":crocodile:",                             "&#x1f40a;"                            },
   { ":croissant:",                             "&#x1f950;"                            },
@@ -376,27 +443,37 @@ static struct emojiEntityInfo
   { ":crystal_ball:",                          "&#x1f52e;"                            },
   { ":cuba:",                                  "&#x1f1e8;&#x1f1fa;"                   },
   { ":cucumber:",                              "&#x1f952;"                            },
+  { ":cup_with_straw:",                        "&#x1f964;"                            },
+  { ":cupcake:",                               "&#x1f9c1;"                            },
   { ":cupid:",                                 "&#x1f498;"                            },
   { ":curacao:",                               "&#x1f1e8;&#x1f1fc;"                   },
+  { ":curling_stone:",                         "&#x1f94c;"                            },
+  { ":curly_haired_man:",                      "&#x1f468;&#x200d;&#x1f9b1;"           },
+  { ":curly_haired_woman:",                    "&#x1f469;&#x200d;&#x1f9b1;"           },
   { ":curly_loop:",                            "&#x27b0;"                             },
   { ":currency_exchange:",                     "&#x1f4b1;"                            },
   { ":curry:",                                 "&#x1f35b;"                            },
+  { ":cursing_face:",                          "&#x1f92c;"                            },
   { ":custard:",                               "&#x1f36e;"                            },
   { ":customs:",                               "&#x1f6c3;"                            },
+  { ":cut_of_meat:",                           "&#x1f969;"                            },
   { ":cyclone:",                               "&#x1f300;"                            },
   { ":cyprus:",                                "&#x1f1e8;&#x1f1fe;"                   },
   { ":czech_republic:",                        "&#x1f1e8;&#x1f1ff;"                   },
   { ":dagger:",                                "&#x1f5e1;"                            },
   { ":dancer:",                                "&#x1f483;"                            },
   { ":dancers:",                               "&#x1f46f;"                            },
-  { ":dancing_men:",                           "&#x1f46f;&#x2642;"                    },
-  { ":dancing_women:",                         "&#x1f46f;"                            },
+  { ":dancing_men:",                           "&#x1f46f;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":dancing_women:",                         "&#x1f46f;&#x200d;&#x2640;&#xfe0f;"    },
   { ":dango:",                                 "&#x1f361;"                            },
   { ":dark_sunglasses:",                       "&#x1f576;"                            },
   { ":dart:",                                  "&#x1f3af;"                            },
   { ":dash:",                                  "&#x1f4a8;"                            },
   { ":date:",                                  "&#x1f4c5;"                            },
   { ":de:",                                    "&#x1f1e9;&#x1f1ea;"                   },
+  { ":deaf_man:",                              "&#x1f9cf;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":deaf_person:",                           "&#x1f9cf;"                            },
+  { ":deaf_woman:",                            "&#x1f9cf;&#x200d;&#x2640;&#xfe0f;"    },
   { ":deciduous_tree:",                        "&#x1f333;"                            },
   { ":deer:",                                  "&#x1f98c;"                            },
   { ":denmark:",                               "&#x1f1e9;&#x1f1f0;"                   },
@@ -408,12 +485,18 @@ static struct emojiEntityInfo
   { ":detective:",                             "&#x1f575;"                            },
   { ":diamond_shape_with_a_dot_inside:",       "&#x1f4a0;"                            },
   { ":diamonds:",                              "&#x2666;"                             },
+  { ":diego_garcia:",                          "&#x1f1e9;&#x1f1ec;"                   },
   { ":disappointed:",                          "&#x1f61e;"                            },
   { ":disappointed_relieved:",                 "&#x1f625;"                            },
+  { ":disguised_face:",                        "&#x1f978;"                            },
+  { ":diving_mask:",                           "&#x1f93f;"                            },
+  { ":diya_lamp:",                             "&#x1fa94;"                            },
   { ":dizzy:",                                 "&#x1f4ab;"                            },
   { ":dizzy_face:",                            "&#x1f635;"                            },
   { ":djibouti:",                              "&#x1f1e9;&#x1f1ef;"                   },
+  { ":dna:",                                   "&#x1f9ec;"                            },
   { ":do_not_litter:",                         "&#x1f6af;"                            },
+  { ":dodo:",                                  "&#x1f9a4;"                            },
   { ":dog:",                                   "&#x1f436;"                            },
   { ":dog2:",                                  "&#x1f415;"                            },
   { ":dollar:",                                "&#x1f4b5;"                            },
@@ -429,14 +512,17 @@ static struct emojiEntityInfo
   { ":dress:",                                 "&#x1f457;"                            },
   { ":dromedary_camel:",                       "&#x1f42a;"                            },
   { ":drooling_face:",                         "&#x1f924;"                            },
+  { ":drop_of_blood:",                         "&#x1fa78;"                            },
   { ":droplet:",                               "&#x1f4a7;"                            },
   { ":drum:",                                  "&#x1f941;"                            },
   { ":duck:",                                  "&#x1f986;"                            },
+  { ":dumpling:",                              "&#x1f95f;"                            },
   { ":dvd:",                                   "&#x1f4c0;"                            },
   { ":e-mail:",                                "&#x1f4e7;"                            },
   { ":eagle:",                                 "&#x1f985;"                            },
   { ":ear:",                                   "&#x1f442;"                            },
   { ":ear_of_rice:",                           "&#x1f33e;"                            },
+  { ":ear_with_hearing_aid:",                  "&#x1f9bb;"                            },
   { ":earth_africa:",                          "&#x1f30d;"                            },
   { ":earth_americas:",                        "&#x1f30e;"                            },
   { ":earth_asia:",                            "&#x1f30f;"                            },
@@ -444,14 +530,20 @@ static struct emojiEntityInfo
   { ":egg:",                                   "&#x1f95a;"                            },
   { ":eggplant:",                              "&#x1f346;"                            },
   { ":egypt:",                                 "&#x1f1ea;&#x1f1ec;"                   },
-  { ":eight:",                                 "&#x0038;&#x20e3;"                     },
+  { ":eight:",                                 "&#x0038;&#xfe0f;&#x20e3;"             },
   { ":eight_pointed_black_star:",              "&#x2734;"                             },
   { ":eight_spoked_asterisk:",                 "&#x2733;"                             },
+  { ":eject_button:",                          "&#x23cf;"                             },
   { ":el_salvador:",                           "&#x1f1f8;&#x1f1fb;"                   },
   { ":electric_plug:",                         "&#x1f50c;"                            },
   { ":elephant:",                              "&#x1f418;"                            },
-  { ":email:",                                 "&#x2709;"                             },
+  { ":elevator:",                              "&#x1f6d7;"                            },
+  { ":elf:",                                   "&#x1f9dd;"                            },
+  { ":elf_man:",                               "&#x1f9dd;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":elf_woman:",                             "&#x1f9dd;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":email:",                                 "&#x1f4e7;"                            },
   { ":end:",                                   "&#x1f51a;"                            },
+  { ":england:",                               "&#x1f3f4;&#xe0067;&#xe0062;&#xe0065;&#xe006e;&#xe0067;&#xe007f;" },
   { ":envelope:",                              "&#x2709;"                             },
   { ":envelope_with_arrow:",                   "&#x1f4e9;"                            },
   { ":equatorial_guinea:",                     "&#x1f1ec;&#x1f1f6;"                   },
@@ -466,49 +558,62 @@ static struct emojiEntityInfo
   { ":european_union:",                        "&#x1f1ea;&#x1f1fa;"                   },
   { ":evergreen_tree:",                        "&#x1f332;"                            },
   { ":exclamation:",                           "&#x2757;"                             },
+  { ":exploding_head:",                        "&#x1f92f;"                            },
   { ":expressionless:",                        "&#x1f611;"                            },
-  { ":eye:",                                   "&#x1f441;"                            },
-  { ":eye_speech_bubble:",                     "&#x1f441;&#x1f5e8;"                   },
+  { ":eye:",                                   "&#x1f441;&#xfe0f;&#x200d;&#x1f5e8;&#xfe0f;" },
+  { ":eye_speech_bubble:",                     "&#x1f441;&#xfe0f;&#x200d;&#x1f5e8;&#xfe0f;" },
   { ":eyeglasses:",                            "&#x1f453;"                            },
   { ":eyes:",                                  "&#x1f440;"                            },
+  { ":face_exhaling:",                         "&#x1f62e;&#x200d;&#x1f4a8;"           },
+  { ":face_in_clouds:",                        "&#x1f636;&#x200d;&#x1f32b;&#xfe0f;"   },
   { ":face_with_head_bandage:",                "&#x1f915;"                            },
+  { ":face_with_spiral_eyes:",                 "&#x1f635;&#x200d;&#x1f4ab;"           },
   { ":face_with_thermometer:",                 "&#x1f912;"                            },
+  { ":facepalm:",                              "&#x1f926;"                            },
   { ":facepunch:",                             "&#x1f44a;"                            },
   { ":factory:",                               "&#x1f3ed;"                            },
+  { ":factory_worker:",                        "&#x1f9d1;&#x200d;&#x1f3ed;"           },
+  { ":fairy:",                                 "&#x1f9da;"                            },
+  { ":fairy_man:",                             "&#x1f9da;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":fairy_woman:",                           "&#x1f9da;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":falafel:",                               "&#x1f9c6;"                            },
   { ":falkland_islands:",                      "&#x1f1eb;&#x1f1f0;"                   },
   { ":fallen_leaf:",                           "&#x1f342;"                            },
   { ":family:",                                "&#x1f46a;"                            },
-  { ":family_man_boy:",                        "&#x1f468;&#x1f466;"                   },
-  { ":family_man_boy_boy:",                    "&#x1f468;&#x1f466;&#x1f466;"          },
-  { ":family_man_girl:",                       "&#x1f468;&#x1f467;"                   },
-  { ":family_man_girl_boy:",                   "&#x1f468;&#x1f467;&#x1f466;"          },
-  { ":family_man_girl_girl:",                  "&#x1f468;&#x1f467;&#x1f467;"          },
-  { ":family_man_man_boy:",                    "&#x1f468;&#x1f468;&#x1f466;"          },
-  { ":family_man_man_boy_boy:",                "&#x1f468;&#x1f468;&#x1f466;&#x1f466;" },
-  { ":family_man_man_girl:",                   "&#x1f468;&#x1f468;&#x1f467;"          },
-  { ":family_man_man_girl_boy:",               "&#x1f468;&#x1f468;&#x1f467;&#x1f466;" },
-  { ":family_man_man_girl_girl:",              "&#x1f468;&#x1f468;&#x1f467;&#x1f467;" },
-  { ":family_man_woman_boy:",                  "&#x1f46a;"                            },
-  { ":family_man_woman_boy_boy:",              "&#x1f468;&#x1f469;&#x1f466;&#x1f466;" },
-  { ":family_man_woman_girl:",                 "&#x1f468;&#x1f469;&#x1f467;"          },
-  { ":family_man_woman_girl_boy:",             "&#x1f468;&#x1f469;&#x1f467;&#x1f466;" },
-  { ":family_man_woman_girl_girl:",            "&#x1f468;&#x1f469;&#x1f467;&#x1f467;" },
-  { ":family_woman_boy:",                      "&#x1f469;&#x1f466;"                   },
-  { ":family_woman_boy_boy:",                  "&#x1f469;&#x1f466;&#x1f466;"          },
-  { ":family_woman_girl:",                     "&#x1f469;&#x1f467;"                   },
-  { ":family_woman_girl_boy:",                 "&#x1f469;&#x1f467;&#x1f466;"          },
-  { ":family_woman_girl_girl:",                "&#x1f469;&#x1f467;&#x1f467;"          },
-  { ":family_woman_woman_boy:",                "&#x1f469;&#x1f469;&#x1f466;"          },
-  { ":family_woman_woman_boy_boy:",            "&#x1f469;&#x1f469;&#x1f466;&#x1f466;" },
-  { ":family_woman_woman_girl:",               "&#x1f469;&#x1f469;&#x1f467;"          },
-  { ":family_woman_woman_girl_boy:",           "&#x1f469;&#x1f469;&#x1f467;&#x1f466;" },
-  { ":family_woman_woman_girl_girl:",          "&#x1f469;&#x1f469;&#x1f467;&#x1f467;" },
+  { ":family_man_boy:",                        "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f466;" },
+  { ":family_man_boy_boy:",                    "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f466;&#x200d;&#x1f466;" },
+  { ":family_man_girl:",                       "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;" },
+  { ":family_man_girl_boy:",                   "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f466;" },
+  { ":family_man_girl_girl:",                  "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f467;" },
+  { ":family_man_man_boy:",                    "&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f466;" },
+  { ":family_man_man_boy_boy:",                "&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f466;&#x200d;&#x1f466;" },
+  { ":family_man_man_girl:",                   "&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f467;" },
+  { ":family_man_man_girl_boy:",               "&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f467;&#x200d;&#x1f466;" },
+  { ":family_man_man_girl_girl:",              "&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f467;&#x200d;&#x1f467;" },
+  { ":family_man_woman_boy:",                  "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f466;" },
+  { ":family_man_woman_boy_boy:",              "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f466;&#x200d;&#x1f466;" },
+  { ":family_man_woman_girl:",                 "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;" },
+  { ":family_man_woman_girl_boy:",             "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f466;" },
+  { ":family_man_woman_girl_girl:",            "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f467;" },
+  { ":family_woman_boy:",                      "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f466;" },
+  { ":family_woman_boy_boy:",                  "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f466;&#x200d;&#x1f466;" },
+  { ":family_woman_girl:",                     "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;" },
+  { ":family_woman_girl_boy:",                 "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f466;" },
+  { ":family_woman_girl_girl:",                "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f467;" },
+  { ":family_woman_woman_boy:",                "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f466;" },
+  { ":family_woman_woman_boy_boy:",            "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f466;&#x200d;&#x1f466;" },
+  { ":family_woman_woman_girl:",               "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;" },
+  { ":family_woman_woman_girl_boy:",           "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f466;" },
+  { ":family_woman_woman_girl_girl:",          "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f467;" },
+  { ":farmer:",                                "&#x1f9d1;&#x200d;&#x1f33e;"           },
   { ":faroe_islands:",                         "&#x1f1eb;&#x1f1f4;"                   },
   { ":fast_forward:",                          "&#x23e9;"                             },
   { ":fax:",                                   "&#x1f4e0;"                            },
   { ":fearful:",                               "&#x1f628;"                            },
+  { ":feather:",                               "&#x1fab6;"                            },
   { ":feet:",                                  "&#x1f43e;"                            },
-  { ":female_detective:",                      "&#x1f575;&#x2640;"                    },
+  { ":female_detective:",                      "&#x1f575;&#xfe0f;&#x200d;&#x2640;&#xfe0f;" },
+  { ":female_sign:",                           "&#x2640;"                             },
   { ":ferris_wheel:",                          "&#x1f3a1;"                            },
   { ":ferry:",                                 "&#x26f4;"                             },
   { ":field_hockey:",                          "&#x1f3d1;"                            },
@@ -520,6 +625,9 @@ static struct emojiEntityInfo
   { ":finland:",                               "&#x1f1eb;&#x1f1ee;"                   },
   { ":fire:",                                  "&#x1f525;"                            },
   { ":fire_engine:",                           "&#x1f692;"                            },
+  { ":fire_extinguisher:",                     "&#x1f9ef;"                            },
+  { ":firecracker:",                           "&#x1f9e8;"                            },
+  { ":firefighter:",                           "&#x1f9d1;&#x200d;&#x1f692;"           },
   { ":fireworks:",                             "&#x1f386;"                            },
   { ":first_quarter_moon:",                    "&#x1f313;"                            },
   { ":first_quarter_moon_with_face:",          "&#x1f31b;"                            },
@@ -531,9 +639,12 @@ static struct emojiEntityInfo
   { ":fist_oncoming:",                         "&#x1f44a;"                            },
   { ":fist_raised:",                           "&#x270a;"                             },
   { ":fist_right:",                            "&#x1f91c;"                            },
-  { ":five:",                                  "&#x0035;&#x20e3;"                     },
+  { ":five:",                                  "&#x0035;&#xfe0f;&#x20e3;"             },
   { ":flags:",                                 "&#x1f38f;"                            },
+  { ":flamingo:",                              "&#x1f9a9;"                            },
   { ":flashlight:",                            "&#x1f526;"                            },
+  { ":flat_shoe:",                             "&#x1f97f;"                            },
+  { ":flatbread:",                             "&#x1fad3;"                            },
   { ":fleur_de_lis:",                          "&#x269c;"                             },
   { ":flight_arrival:",                        "&#x1f6ec;"                            },
   { ":flight_departure:",                      "&#x1f6eb;"                            },
@@ -541,14 +652,20 @@ static struct emojiEntityInfo
   { ":floppy_disk:",                           "&#x1f4be;"                            },
   { ":flower_playing_cards:",                  "&#x1f3b4;"                            },
   { ":flushed:",                               "&#x1f633;"                            },
+  { ":fly:",                                   "&#x1fab0;"                            },
+  { ":flying_disc:",                           "&#x1f94f;"                            },
+  { ":flying_saucer:",                         "&#x1f6f8;"                            },
   { ":fog:",                                   "&#x1f32b;"                            },
   { ":foggy:",                                 "&#x1f301;"                            },
+  { ":fondue:",                                "&#x1fad5;"                            },
+  { ":foot:",                                  "&#x1f9b6;"                            },
   { ":football:",                              "&#x1f3c8;"                            },
   { ":footprints:",                            "&#x1f463;"                            },
   { ":fork_and_knife:",                        "&#x1f374;"                            },
+  { ":fortune_cookie:",                        "&#x1f960;"                            },
   { ":fountain:",                              "&#x26f2;"                             },
   { ":fountain_pen:",                          "&#x1f58b;"                            },
-  { ":four:",                                  "&#x0034;&#x20e3;"                     },
+  { ":four:",                                  "&#x0034;&#xfe0f;&#x20e3;"             },
   { ":four_leaf_clover:",                      "&#x1f340;"                            },
   { ":fox_face:",                              "&#x1f98a;"                            },
   { ":fr:",                                    "&#x1f1eb;&#x1f1f7;"                   },
@@ -563,8 +680,9 @@ static struct emojiEntityInfo
   { ":frog:",                                  "&#x1f438;"                            },
   { ":frowning:",                              "&#x1f626;"                            },
   { ":frowning_face:",                         "&#x2639;"                             },
-  { ":frowning_man:",                          "&#x1f64d;&#x2642;"                    },
-  { ":frowning_woman:",                        "&#x1f64d;"                            },
+  { ":frowning_man:",                          "&#x1f64d;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":frowning_person:",                       "&#x1f64d;"                            },
+  { ":frowning_woman:",                        "&#x1f64d;&#x200d;&#x2640;&#xfe0f;"    },
   { ":fu:",                                    "&#x1f595;"                            },
   { ":fuelpump:",                              "&#x26fd;"                             },
   { ":full_moon:",                             "&#x1f315;"                            },
@@ -573,30 +691,40 @@ static struct emojiEntityInfo
   { ":gabon:",                                 "&#x1f1ec;&#x1f1e6;"                   },
   { ":gambia:",                                "&#x1f1ec;&#x1f1f2;"                   },
   { ":game_die:",                              "&#x1f3b2;"                            },
+  { ":garlic:",                                "&#x1f9c4;"                            },
   { ":gb:",                                    "&#x1f1ec;&#x1f1e7;"                   },
   { ":gear:",                                  "&#x2699;"                             },
   { ":gem:",                                   "&#x1f48e;"                            },
   { ":gemini:",                                "&#x264a;"                             },
+  { ":genie:",                                 "&#x1f9de;"                            },
+  { ":genie_man:",                             "&#x1f9de;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":genie_woman:",                           "&#x1f9de;&#x200d;&#x2640;&#xfe0f;"    },
   { ":georgia:",                               "&#x1f1ec;&#x1f1ea;"                   },
   { ":ghana:",                                 "&#x1f1ec;&#x1f1ed;"                   },
   { ":ghost:",                                 "&#x1f47b;"                            },
   { ":gibraltar:",                             "&#x1f1ec;&#x1f1ee;"                   },
   { ":gift:",                                  "&#x1f381;"                            },
   { ":gift_heart:",                            "&#x1f49d;"                            },
+  { ":giraffe:",                               "&#x1f992;"                            },
   { ":girl:",                                  "&#x1f467;"                            },
   { ":globe_with_meridians:",                  "&#x1f310;"                            },
+  { ":gloves:",                                "&#x1f9e4;"                            },
   { ":goal_net:",                              "&#x1f945;"                            },
   { ":goat:",                                  "&#x1f410;"                            },
+  { ":goggles:",                               "&#x1f97d;"                            },
   { ":golf:",                                  "&#x26f3;"                             },
-  { ":golfing_man:",                           "&#x1f3cc;"                            },
-  { ":golfing_woman:",                         "&#x1f3cc;&#x2640;"                    },
+  { ":golfing:",                               "&#x1f3cc;"                            },
+  { ":golfing_man:",                           "&#x1f3cc;&#xfe0f;&#x200d;&#x2642;&#xfe0f;" },
+  { ":golfing_woman:",                         "&#x1f3cc;&#xfe0f;&#x200d;&#x2640;&#xfe0f;" },
   { ":gorilla:",                               "&#x1f98d;"                            },
   { ":grapes:",                                "&#x1f347;"                            },
   { ":greece:",                                "&#x1f1ec;&#x1f1f7;"                   },
   { ":green_apple:",                           "&#x1f34f;"                            },
   { ":green_book:",                            "&#x1f4d7;"                            },
+  { ":green_circle:",                          "&#x1f7e2;"                            },
   { ":green_heart:",                           "&#x1f49a;"                            },
   { ":green_salad:",                           "&#x1f957;"                            },
+  { ":green_square:",                          "&#x1f7e9;"                            },
   { ":greenland:",                             "&#x1f1ec;&#x1f1f1;"                   },
   { ":grenada:",                               "&#x1f1ec;&#x1f1e9;"                   },
   { ":grey_exclamation:",                      "&#x2755;"                             },
@@ -606,18 +734,20 @@ static struct emojiEntityInfo
   { ":grinning:",                              "&#x1f600;"                            },
   { ":guadeloupe:",                            "&#x1f1ec;&#x1f1f5;"                   },
   { ":guam:",                                  "&#x1f1ec;&#x1f1fa;"                   },
-  { ":guardsman:",                             "&#x1f482;"                            },
-  { ":guardswoman:",                           "&#x1f482;&#x2640;"                    },
+  { ":guard:",                                 "&#x1f482;"                            },
+  { ":guardsman:",                             "&#x1f482;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":guardswoman:",                           "&#x1f482;&#x200d;&#x2640;&#xfe0f;"    },
   { ":guatemala:",                             "&#x1f1ec;&#x1f1f9;"                   },
   { ":guernsey:",                              "&#x1f1ec;&#x1f1ec;"                   },
+  { ":guide_dog:",                             "&#x1f9ae;"                            },
   { ":guinea:",                                "&#x1f1ec;&#x1f1f3;"                   },
   { ":guinea_bissau:",                         "&#x1f1ec;&#x1f1fc;"                   },
   { ":guitar:",                                "&#x1f3b8;"                            },
   { ":gun:",                                   "&#x1f52b;"                            },
   { ":guyana:",                                "&#x1f1ec;&#x1f1fe;"                   },
   { ":haircut:",                               "&#x1f487;"                            },
-  { ":haircut_man:",                           "&#x1f487;&#x2642;"                    },
-  { ":haircut_woman:",                         "&#x1f487;"                            },
+  { ":haircut_man:",                           "&#x1f487;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":haircut_woman:",                         "&#x1f487;&#x200d;&#x2640;&#xfe0f;"    },
   { ":haiti:",                                 "&#x1f1ed;&#x1f1f9;"                   },
   { ":hamburger:",                             "&#x1f354;"                            },
   { ":hammer:",                                "&#x1f528;"                            },
@@ -625,18 +755,24 @@ static struct emojiEntityInfo
   { ":hammer_and_wrench:",                     "&#x1f6e0;"                            },
   { ":hamster:",                               "&#x1f439;"                            },
   { ":hand:",                                  "&#x270b;"                             },
+  { ":hand_over_mouth:",                       "&#x1f92d;"                            },
   { ":handbag:",                               "&#x1f45c;"                            },
+  { ":handball_person:",                       "&#x1f93e;"                            },
   { ":handshake:",                             "&#x1f91d;"                            },
   { ":hankey:",                                "&#x1f4a9;"                            },
-  { ":hash:",                                  "&#x0023;&#x20e3;"                     },
+  { ":hash:",                                  "&#x0023;&#xfe0f;&#x20e3;"             },
   { ":hatched_chick:",                         "&#x1f425;"                            },
   { ":hatching_chick:",                        "&#x1f423;"                            },
   { ":headphones:",                            "&#x1f3a7;"                            },
+  { ":headstone:",                             "&#x1faa6;"                            },
+  { ":health_worker:",                         "&#x1f9d1;&#x200d;&#x2695;&#xfe0f;"    },
   { ":hear_no_evil:",                          "&#x1f649;"                            },
-  { ":heart:",                                 "&#x2764;"                             },
+  { ":heard_mcdonald_islands:",                "&#x1f1ed;&#x1f1f2;"                   },
+  { ":heart:",                                 "&#x2764;&#xfe0f;&#x200d;&#x1f525;"    },
   { ":heart_decoration:",                      "&#x1f49f;"                            },
   { ":heart_eyes:",                            "&#x1f60d;"                            },
   { ":heart_eyes_cat:",                        "&#x1f63b;"                            },
+  { ":heart_on_fire:",                         "&#x2764;&#xfe0f;&#x200d;&#x1f525;"    },
   { ":heartbeat:",                             "&#x1f493;"                            },
   { ":heartpulse:",                            "&#x1f497;"                            },
   { ":hearts:",                                "&#x2665;"                             },
@@ -648,20 +784,26 @@ static struct emojiEntityInfo
   { ":heavy_minus_sign:",                      "&#x2796;"                             },
   { ":heavy_multiplication_x:",                "&#x2716;"                             },
   { ":heavy_plus_sign:",                       "&#x2795;"                             },
+  { ":hedgehog:",                              "&#x1f994;"                            },
   { ":helicopter:",                            "&#x1f681;"                            },
   { ":herb:",                                  "&#x1f33f;"                            },
   { ":hibiscus:",                              "&#x1f33a;"                            },
   { ":high_brightness:",                       "&#x1f506;"                            },
   { ":high_heel:",                             "&#x1f460;"                            },
+  { ":hiking_boot:",                           "&#x1f97e;"                            },
+  { ":hindu_temple:",                          "&#x1f6d5;"                            },
+  { ":hippopotamus:",                          "&#x1f99b;"                            },
   { ":hocho:",                                 "&#x1f52a;"                            },
   { ":hole:",                                  "&#x1f573;"                            },
   { ":honduras:",                              "&#x1f1ed;&#x1f1f3;"                   },
   { ":honey_pot:",                             "&#x1f36f;"                            },
   { ":honeybee:",                              "&#x1f41d;"                            },
   { ":hong_kong:",                             "&#x1f1ed;&#x1f1f0;"                   },
+  { ":hook:",                                  "&#x1fa9d;"                            },
   { ":horse:",                                 "&#x1f434;"                            },
   { ":horse_racing:",                          "&#x1f3c7;"                            },
   { ":hospital:",                              "&#x1f3e5;"                            },
+  { ":hot_face:",                              "&#x1f975;"                            },
   { ":hot_pepper:",                            "&#x1f336;"                            },
   { ":hotdog:",                                "&#x1f32d;"                            },
   { ":hotel:",                                 "&#x1f3e8;"                            },
@@ -674,7 +816,9 @@ static struct emojiEntityInfo
   { ":hugs:",                                  "&#x1f917;"                            },
   { ":hungary:",                               "&#x1f1ed;&#x1f1fa;"                   },
   { ":hushed:",                                "&#x1f62f;"                            },
+  { ":hut:",                                   "&#x1f6d6;"                            },
   { ":ice_cream:",                             "&#x1f368;"                            },
+  { ":ice_cube:",                              "&#x1f9ca;"                            },
   { ":ice_hockey:",                            "&#x1f3d2;"                            },
   { ":ice_skate:",                             "&#x26f8;"                             },
   { ":icecream:",                              "&#x1f366;"                            },
@@ -686,6 +830,7 @@ static struct emojiEntityInfo
   { ":incoming_envelope:",                     "&#x1f4e8;"                            },
   { ":india:",                                 "&#x1f1ee;&#x1f1f3;"                   },
   { ":indonesia:",                             "&#x1f1ee;&#x1f1e9;"                   },
+  { ":infinity:",                              "&#x267e;"                             },
   { ":information_desk_person:",               "&#x1f481;"                            },
   { ":information_source:",                    "&#x2139;"                             },
   { ":innocent:",                              "&#x1f607;"                            },
@@ -706,12 +851,16 @@ static struct emojiEntityInfo
   { ":japanese_ogre:",                         "&#x1f479;"                            },
   { ":jeans:",                                 "&#x1f456;"                            },
   { ":jersey:",                                "&#x1f1ef;&#x1f1ea;"                   },
+  { ":jigsaw:",                                "&#x1f9e9;"                            },
   { ":jordan:",                                "&#x1f1ef;&#x1f1f4;"                   },
   { ":joy:",                                   "&#x1f602;"                            },
   { ":joy_cat:",                               "&#x1f639;"                            },
   { ":joystick:",                              "&#x1f579;"                            },
   { ":jp:",                                    "&#x1f1ef;&#x1f1f5;"                   },
+  { ":judge:",                                 "&#x1f9d1;&#x200d;&#x2696;&#xfe0f;"    },
+  { ":juggling_person:",                       "&#x1f939;"                            },
   { ":kaaba:",                                 "&#x1f54b;"                            },
+  { ":kangaroo:",                              "&#x1f998;"                            },
   { ":kazakhstan:",                            "&#x1f1f0;&#x1f1ff;"                   },
   { ":kenya:",                                 "&#x1f1f0;&#x1f1ea;"                   },
   { ":key:",                                   "&#x1f511;"                            },
@@ -726,15 +875,24 @@ static struct emojiEntityInfo
   { ":kissing_closed_eyes:",                   "&#x1f61a;"                            },
   { ":kissing_heart:",                         "&#x1f618;"                            },
   { ":kissing_smiling_eyes:",                  "&#x1f619;"                            },
+  { ":kite:",                                  "&#x1fa81;"                            },
   { ":kiwi_fruit:",                            "&#x1f95d;"                            },
+  { ":kneeling_man:",                          "&#x1f9ce;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":kneeling_person:",                       "&#x1f9ce;"                            },
+  { ":kneeling_woman:",                        "&#x1f9ce;&#x200d;&#x2640;&#xfe0f;"    },
   { ":knife:",                                 "&#x1f52a;"                            },
+  { ":knot:",                                  "&#x1faa2;"                            },
   { ":koala:",                                 "&#x1f428;"                            },
   { ":koko:",                                  "&#x1f201;"                            },
   { ":kosovo:",                                "&#x1f1fd;&#x1f1f0;"                   },
   { ":kr:",                                    "&#x1f1f0;&#x1f1f7;"                   },
   { ":kuwait:",                                "&#x1f1f0;&#x1f1fc;"                   },
   { ":kyrgyzstan:",                            "&#x1f1f0;&#x1f1ec;"                   },
+  { ":lab_coat:",                              "&#x1f97c;"                            },
   { ":label:",                                 "&#x1f3f7;"                            },
+  { ":lacrosse:",                              "&#x1f94d;"                            },
+  { ":ladder:",                                "&#x1fa9c;"                            },
+  { ":lady_beetle:",                           "&#x1f41e;"                            },
   { ":lantern:",                               "&#x1f3ee;"                            },
   { ":laos:",                                  "&#x1f1f1;&#x1f1e6;"                   },
   { ":large_blue_circle:",                     "&#x1f535;"                            },
@@ -745,12 +903,15 @@ static struct emojiEntityInfo
   { ":latin_cross:",                           "&#x271d;"                             },
   { ":latvia:",                                "&#x1f1f1;&#x1f1fb;"                   },
   { ":laughing:",                              "&#x1f606;"                            },
+  { ":leafy_green:",                           "&#x1f96c;"                            },
   { ":leaves:",                                "&#x1f343;"                            },
   { ":lebanon:",                               "&#x1f1f1;&#x1f1e7;"                   },
   { ":ledger:",                                "&#x1f4d2;"                            },
   { ":left_luggage:",                          "&#x1f6c5;"                            },
   { ":left_right_arrow:",                      "&#x2194;"                             },
+  { ":left_speech_bubble:",                    "&#x1f5e8;"                            },
   { ":leftwards_arrow_with_hook:",             "&#x21a9;"                             },
+  { ":leg:",                                   "&#x1f9b5;"                            },
   { ":lemon:",                                 "&#x1f34b;"                            },
   { ":leo:",                                   "&#x264c;"                             },
   { ":leopard:",                               "&#x1f406;"                            },
@@ -767,15 +928,25 @@ static struct emojiEntityInfo
   { ":lipstick:",                              "&#x1f484;"                            },
   { ":lithuania:",                             "&#x1f1f1;&#x1f1f9;"                   },
   { ":lizard:",                                "&#x1f98e;"                            },
+  { ":llama:",                                 "&#x1f999;"                            },
+  { ":lobster:",                               "&#x1f99e;"                            },
   { ":lock:",                                  "&#x1f512;"                            },
   { ":lock_with_ink_pen:",                     "&#x1f50f;"                            },
   { ":lollipop:",                              "&#x1f36d;"                            },
+  { ":long_drum:",                             "&#x1fa98;"                            },
   { ":loop:",                                  "&#x27bf;"                             },
+  { ":lotion_bottle:",                         "&#x1f9f4;"                            },
+  { ":lotus_position:",                        "&#x1f9d8;"                            },
+  { ":lotus_position_man:",                    "&#x1f9d8;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":lotus_position_woman:",                  "&#x1f9d8;&#x200d;&#x2640;&#xfe0f;"    },
   { ":loud_sound:",                            "&#x1f50a;"                            },
   { ":loudspeaker:",                           "&#x1f4e2;"                            },
   { ":love_hotel:",                            "&#x1f3e9;"                            },
   { ":love_letter:",                           "&#x1f48c;"                            },
+  { ":love_you_gesture:",                      "&#x1f91f;"                            },
   { ":low_brightness:",                        "&#x1f505;"                            },
+  { ":luggage:",                               "&#x1f9f3;"                            },
+  { ":lungs:",                                 "&#x1fac1;"                            },
   { ":luxembourg:",                            "&#x1f1f1;&#x1f1fa;"                   },
   { ":lying_face:",                            "&#x1f925;"                            },
   { ":m:",                                     "&#x24c2;"                             },
@@ -784,6 +955,11 @@ static struct emojiEntityInfo
   { ":madagascar:",                            "&#x1f1f2;&#x1f1ec;"                   },
   { ":mag:",                                   "&#x1f50d;"                            },
   { ":mag_right:",                             "&#x1f50e;"                            },
+  { ":mage:",                                  "&#x1f9d9;"                            },
+  { ":mage_man:",                              "&#x1f9d9;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":mage_woman:",                            "&#x1f9d9;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":magic_wand:",                            "&#x1fa84;"                            },
+  { ":magnet:",                                "&#x1f9f2;"                            },
   { ":mahjong:",                               "&#x1f004;"                            },
   { ":mailbox:",                               "&#x1f4eb;"                            },
   { ":mailbox_closed:",                        "&#x1f4ea;"                            },
@@ -792,70 +968,92 @@ static struct emojiEntityInfo
   { ":malawi:",                                "&#x1f1f2;&#x1f1fc;"                   },
   { ":malaysia:",                              "&#x1f1f2;&#x1f1fe;"                   },
   { ":maldives:",                              "&#x1f1f2;&#x1f1fb;"                   },
-  { ":male_detective:",                        "&#x1f575;"                            },
+  { ":male_detective:",                        "&#x1f575;&#xfe0f;&#x200d;&#x2642;&#xfe0f;" },
+  { ":male_sign:",                             "&#x2642;"                             },
   { ":mali:",                                  "&#x1f1f2;&#x1f1f1;"                   },
   { ":malta:",                                 "&#x1f1f2;&#x1f1f9;"                   },
+  { ":mammoth:",                               "&#x1f9a3;"                            },
   { ":man:",                                   "&#x1f468;"                            },
-  { ":man_artist:",                            "&#x1f468;&#x1f3a8;"                   },
-  { ":man_astronaut:",                         "&#x1f468;&#x1f680;"                   },
-  { ":man_cartwheeling:",                      "&#x1f938;&#x2642;"                    },
-  { ":man_cook:",                              "&#x1f468;&#x1f373;"                   },
+  { ":man_artist:",                            "&#x1f468;&#x200d;&#x1f3a8;"           },
+  { ":man_astronaut:",                         "&#x1f468;&#x200d;&#x1f680;"           },
+  { ":man_beard:",                             "&#x1f9d4;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":man_cartwheeling:",                      "&#x1f938;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":man_cook:",                              "&#x1f468;&#x200d;&#x1f373;"           },
   { ":man_dancing:",                           "&#x1f57a;"                            },
-  { ":man_facepalming:",                       "&#x1f926;&#x2642;"                    },
-  { ":man_factory_worker:",                    "&#x1f468;&#x1f3ed;"                   },
-  { ":man_farmer:",                            "&#x1f468;&#x1f33e;"                   },
-  { ":man_firefighter:",                       "&#x1f468;&#x1f692;"                   },
-  { ":man_health_worker:",                     "&#x1f468;&#x2695;"                    },
-  { ":man_in_tuxedo:",                         "&#x1f935;"                            },
-  { ":man_judge:",                             "&#x1f468;&#x2696;"                    },
-  { ":man_juggling:",                          "&#x1f939;&#x2642;"                    },
-  { ":man_mechanic:",                          "&#x1f468;&#x1f527;"                   },
-  { ":man_office_worker:",                     "&#x1f468;&#x1f4bc;"                   },
-  { ":man_pilot:",                             "&#x1f468;&#x2708;"                    },
-  { ":man_playing_handball:",                  "&#x1f93e;&#x2642;"                    },
-  { ":man_playing_water_polo:",                "&#x1f93d;&#x2642;"                    },
-  { ":man_scientist:",                         "&#x1f468;&#x1f52c;"                   },
-  { ":man_shrugging:",                         "&#x1f937;&#x2642;"                    },
-  { ":man_singer:",                            "&#x1f468;&#x1f3a4;"                   },
-  { ":man_student:",                           "&#x1f468;&#x1f393;"                   },
-  { ":man_teacher:",                           "&#x1f468;&#x1f3eb;"                   },
-  { ":man_technologist:",                      "&#x1f468;&#x1f4bb;"                   },
+  { ":man_facepalming:",                       "&#x1f926;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":man_factory_worker:",                    "&#x1f468;&#x200d;&#x1f3ed;"           },
+  { ":man_farmer:",                            "&#x1f468;&#x200d;&#x1f33e;"           },
+  { ":man_feeding_baby:",                      "&#x1f468;&#x200d;&#x1f37c;"           },
+  { ":man_firefighter:",                       "&#x1f468;&#x200d;&#x1f692;"           },
+  { ":man_health_worker:",                     "&#x1f468;&#x200d;&#x2695;&#xfe0f;"    },
+  { ":man_in_manual_wheelchair:",              "&#x1f468;&#x200d;&#x1f9bd;"           },
+  { ":man_in_motorized_wheelchair:",           "&#x1f468;&#x200d;&#x1f9bc;"           },
+  { ":man_in_tuxedo:",                         "&#x1f935;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":man_judge:",                             "&#x1f468;&#x200d;&#x2696;&#xfe0f;"    },
+  { ":man_juggling:",                          "&#x1f939;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":man_mechanic:",                          "&#x1f468;&#x200d;&#x1f527;"           },
+  { ":man_office_worker:",                     "&#x1f468;&#x200d;&#x1f4bc;"           },
+  { ":man_pilot:",                             "&#x1f468;&#x200d;&#x2708;&#xfe0f;"    },
+  { ":man_playing_handball:",                  "&#x1f93e;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":man_playing_water_polo:",                "&#x1f93d;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":man_scientist:",                         "&#x1f468;&#x200d;&#x1f52c;"           },
+  { ":man_shrugging:",                         "&#x1f937;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":man_singer:",                            "&#x1f468;&#x200d;&#x1f3a4;"           },
+  { ":man_student:",                           "&#x1f468;&#x200d;&#x1f393;"           },
+  { ":man_teacher:",                           "&#x1f468;&#x200d;&#x1f3eb;"           },
+  { ":man_technologist:",                      "&#x1f468;&#x200d;&#x1f4bb;"           },
   { ":man_with_gua_pi_mao:",                   "&#x1f472;"                            },
-  { ":man_with_turban:",                       "&#x1f473;"                            },
+  { ":man_with_probing_cane:",                 "&#x1f468;&#x200d;&#x1f9af;"           },
+  { ":man_with_turban:",                       "&#x1f473;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":man_with_veil:",                         "&#x1f470;&#x200d;&#x2642;&#xfe0f;"    },
   { ":mandarin:",                              "&#x1f34a;"                            },
+  { ":mango:",                                 "&#x1f96d;"                            },
   { ":mans_shoe:",                             "&#x1f45e;"                            },
   { ":mantelpiece_clock:",                     "&#x1f570;"                            },
+  { ":manual_wheelchair:",                     "&#x1f9bd;"                            },
   { ":maple_leaf:",                            "&#x1f341;"                            },
   { ":marshall_islands:",                      "&#x1f1f2;&#x1f1ed;"                   },
   { ":martial_arts_uniform:",                  "&#x1f94b;"                            },
   { ":martinique:",                            "&#x1f1f2;&#x1f1f6;"                   },
   { ":mask:",                                  "&#x1f637;"                            },
   { ":massage:",                               "&#x1f486;"                            },
-  { ":massage_man:",                           "&#x1f486;&#x2642;"                    },
-  { ":massage_woman:",                         "&#x1f486;"                            },
+  { ":massage_man:",                           "&#x1f486;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":massage_woman:",                         "&#x1f486;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":mate:",                                  "&#x1f9c9;"                            },
   { ":mauritania:",                            "&#x1f1f2;&#x1f1f7;"                   },
   { ":mauritius:",                             "&#x1f1f2;&#x1f1fa;"                   },
   { ":mayotte:",                               "&#x1f1fe;&#x1f1f9;"                   },
   { ":meat_on_bone:",                          "&#x1f356;"                            },
+  { ":mechanic:",                              "&#x1f9d1;&#x200d;&#x1f527;"           },
+  { ":mechanical_arm:",                        "&#x1f9be;"                            },
+  { ":mechanical_leg:",                        "&#x1f9bf;"                            },
   { ":medal_military:",                        "&#x1f396;"                            },
   { ":medal_sports:",                          "&#x1f3c5;"                            },
+  { ":medical_symbol:",                        "&#x2695;"                             },
   { ":mega:",                                  "&#x1f4e3;"                            },
   { ":melon:",                                 "&#x1f348;"                            },
   { ":memo:",                                  "&#x1f4dd;"                            },
-  { ":men_wrestling:",                         "&#x1f93c;&#x2642;"                    },
+  { ":men_wrestling:",                         "&#x1f93c;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":mending_heart:",                         "&#x2764;&#xfe0f;&#x200d;&#x1fa79;"    },
   { ":menorah:",                               "&#x1f54e;"                            },
   { ":mens:",                                  "&#x1f6b9;"                            },
+  { ":mermaid:",                               "&#x1f9dc;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":merman:",                                "&#x1f9dc;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":merperson:",                             "&#x1f9dc;"                            },
   { ":metal:",                                 "&#x1f918;"                            },
   { ":metro:",                                 "&#x1f687;"                            },
   { ":mexico:",                                "&#x1f1f2;&#x1f1fd;"                   },
+  { ":microbe:",                               "&#x1f9a0;"                            },
   { ":micronesia:",                            "&#x1f1eb;&#x1f1f2;"                   },
   { ":microphone:",                            "&#x1f3a4;"                            },
   { ":microscope:",                            "&#x1f52c;"                            },
   { ":middle_finger:",                         "&#x1f595;"                            },
+  { ":military_helmet:",                       "&#x1fa96;"                            },
   { ":milk_glass:",                            "&#x1f95b;"                            },
   { ":milky_way:",                             "&#x1f30c;"                            },
   { ":minibus:",                               "&#x1f690;"                            },
   { ":minidisc:",                              "&#x1f4bd;"                            },
+  { ":mirror:",                                "&#x1fa9e;"                            },
   { ":mobile_phone_off:",                      "&#x1f4f4;"                            },
   { ":moldova:",                               "&#x1f1f2;&#x1f1e9;"                   },
   { ":monaco:",                                "&#x1f1f2;&#x1f1e8;"                   },
@@ -865,27 +1063,32 @@ static struct emojiEntityInfo
   { ":mongolia:",                              "&#x1f1f2;&#x1f1f3;"                   },
   { ":monkey:",                                "&#x1f412;"                            },
   { ":monkey_face:",                           "&#x1f435;"                            },
+  { ":monocle_face:",                          "&#x1f9d0;"                            },
   { ":monorail:",                              "&#x1f69d;"                            },
   { ":montenegro:",                            "&#x1f1f2;&#x1f1ea;"                   },
   { ":montserrat:",                            "&#x1f1f2;&#x1f1f8;"                   },
   { ":moon:",                                  "&#x1f314;"                            },
+  { ":moon_cake:",                             "&#x1f96e;"                            },
   { ":morocco:",                               "&#x1f1f2;&#x1f1e6;"                   },
   { ":mortar_board:",                          "&#x1f393;"                            },
   { ":mosque:",                                "&#x1f54c;"                            },
+  { ":mosquito:",                              "&#x1f99f;"                            },
   { ":motor_boat:",                            "&#x1f6e5;"                            },
   { ":motor_scooter:",                         "&#x1f6f5;"                            },
   { ":motorcycle:",                            "&#x1f3cd;"                            },
+  { ":motorized_wheelchair:",                  "&#x1f9bc;"                            },
   { ":motorway:",                              "&#x1f6e3;"                            },
   { ":mount_fuji:",                            "&#x1f5fb;"                            },
   { ":mountain:",                              "&#x26f0;"                             },
   { ":mountain_bicyclist:",                    "&#x1f6b5;"                            },
-  { ":mountain_biking_man:",                   "&#x1f6b5;"                            },
-  { ":mountain_biking_woman:",                 "&#x1f6b5;&#x2640;"                    },
+  { ":mountain_biking_man:",                   "&#x1f6b5;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":mountain_biking_woman:",                 "&#x1f6b5;&#x200d;&#x2640;&#xfe0f;"    },
   { ":mountain_cableway:",                     "&#x1f6a0;"                            },
   { ":mountain_railway:",                      "&#x1f69e;"                            },
   { ":mountain_snow:",                         "&#x1f3d4;"                            },
   { ":mouse:",                                 "&#x1f42d;"                            },
   { ":mouse2:",                                "&#x1f401;"                            },
+  { ":mouse_trap:",                            "&#x1faa4;"                            },
   { ":movie_camera:",                          "&#x1f3a5;"                            },
   { ":moyai:",                                 "&#x1f5ff;"                            },
   { ":mozambique:",                            "&#x1f1f2;&#x1f1ff;"                   },
@@ -896,6 +1099,7 @@ static struct emojiEntityInfo
   { ":musical_note:",                          "&#x1f3b5;"                            },
   { ":musical_score:",                         "&#x1f3bc;"                            },
   { ":mute:",                                  "&#x1f507;"                            },
+  { ":mx_claus:",                              "&#x1f9d1;&#x200d;&#x1f384;"           },
   { ":myanmar:",                               "&#x1f1f2;&#x1f1f2;"                   },
   { ":nail_care:",                             "&#x1f485;"                            },
   { ":name_badge:",                            "&#x1f4db;"                            },
@@ -903,10 +1107,12 @@ static struct emojiEntityInfo
   { ":national_park:",                         "&#x1f3de;"                            },
   { ":nauru:",                                 "&#x1f1f3;&#x1f1f7;"                   },
   { ":nauseated_face:",                        "&#x1f922;"                            },
+  { ":nazar_amulet:",                          "&#x1f9ff;"                            },
   { ":necktie:",                               "&#x1f454;"                            },
   { ":negative_squared_cross_mark:",           "&#x274e;"                             },
   { ":nepal:",                                 "&#x1f1f3;&#x1f1f5;"                   },
   { ":nerd_face:",                             "&#x1f913;"                            },
+  { ":nesting_dolls:",                         "&#x1fa86;"                            },
   { ":netherlands:",                           "&#x1f1f3;&#x1f1f1;"                   },
   { ":neutral_face:",                          "&#x1f610;"                            },
   { ":new:",                                   "&#x1f195;"                            },
@@ -918,21 +1124,22 @@ static struct emojiEntityInfo
   { ":newspaper_roll:",                        "&#x1f5de;"                            },
   { ":next_track_button:",                     "&#x23ed;"                             },
   { ":ng:",                                    "&#x1f196;"                            },
-  { ":ng_man:",                                "&#x1f645;&#x2642;"                    },
-  { ":ng_woman:",                              "&#x1f645;"                            },
+  { ":ng_man:",                                "&#x1f645;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":ng_woman:",                              "&#x1f645;&#x200d;&#x2640;&#xfe0f;"    },
   { ":nicaragua:",                             "&#x1f1f3;&#x1f1ee;"                   },
   { ":niger:",                                 "&#x1f1f3;&#x1f1ea;"                   },
   { ":nigeria:",                               "&#x1f1f3;&#x1f1ec;"                   },
   { ":night_with_stars:",                      "&#x1f303;"                            },
-  { ":nine:",                                  "&#x0039;&#x20e3;"                     },
+  { ":nine:",                                  "&#x0039;&#xfe0f;&#x20e3;"             },
+  { ":ninja:",                                 "&#x1f977;"                            },
   { ":niue:",                                  "&#x1f1f3;&#x1f1fa;"                   },
   { ":no_bell:",                               "&#x1f515;"                            },
   { ":no_bicycles:",                           "&#x1f6b3;"                            },
   { ":no_entry:",                              "&#x26d4;"                             },
   { ":no_entry_sign:",                         "&#x1f6ab;"                            },
   { ":no_good:",                               "&#x1f645;"                            },
-  { ":no_good_man:",                           "&#x1f645;&#x2642;"                    },
-  { ":no_good_woman:",                         "&#x1f645;"                            },
+  { ":no_good_man:",                           "&#x1f645;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":no_good_woman:",                         "&#x1f645;&#x200d;&#x2640;&#xfe0f;"    },
   { ":no_mobile_phones:",                      "&#x1f4f5;"                            },
   { ":no_mouth:",                              "&#x1f636;"                            },
   { ":no_pedestrians:",                        "&#x1f6b7;"                            },
@@ -953,14 +1160,18 @@ static struct emojiEntityInfo
   { ":octopus:",                               "&#x1f419;"                            },
   { ":oden:",                                  "&#x1f362;"                            },
   { ":office:",                                "&#x1f3e2;"                            },
+  { ":office_worker:",                         "&#x1f9d1;&#x200d;&#x1f4bc;"           },
   { ":oil_drum:",                              "&#x1f6e2;"                            },
   { ":ok:",                                    "&#x1f197;"                            },
   { ":ok_hand:",                               "&#x1f44c;"                            },
-  { ":ok_man:",                                "&#x1f646;&#x2642;"                    },
-  { ":ok_woman:",                              "&#x1f646;"                            },
+  { ":ok_man:",                                "&#x1f646;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":ok_person:",                             "&#x1f646;"                            },
+  { ":ok_woman:",                              "&#x1f646;&#x200d;&#x2640;&#xfe0f;"    },
   { ":old_key:",                               "&#x1f5dd;"                            },
+  { ":older_adult:",                           "&#x1f9d3;"                            },
   { ":older_man:",                             "&#x1f474;"                            },
   { ":older_woman:",                           "&#x1f475;"                            },
+  { ":olive:",                                 "&#x1fad2;"                            },
   { ":om:",                                    "&#x1f549;"                            },
   { ":oman:",                                  "&#x1f1f4;&#x1f1f2;"                   },
   { ":on:",                                    "&#x1f51b;"                            },
@@ -968,19 +1179,27 @@ static struct emojiEntityInfo
   { ":oncoming_bus:",                          "&#x1f68d;"                            },
   { ":oncoming_police_car:",                   "&#x1f694;"                            },
   { ":oncoming_taxi:",                         "&#x1f696;"                            },
-  { ":one:",                                   "&#x0031;&#x20e3;"                     },
+  { ":one:",                                   "&#x0031;&#xfe0f;&#x20e3;"             },
+  { ":one_piece_swimsuit:",                    "&#x1fa71;"                            },
+  { ":onion:",                                 "&#x1f9c5;"                            },
   { ":open_book:",                             "&#x1f4d6;"                            },
   { ":open_file_folder:",                      "&#x1f4c2;"                            },
   { ":open_hands:",                            "&#x1f450;"                            },
-  { ":open_mouth:",                            "&#x1f62e;"                            },
+  { ":open_mouth:",                            "&#x1f62e;&#x200d;&#x1f4a8;"           },
   { ":open_umbrella:",                         "&#x2602;"                             },
   { ":ophiuchus:",                             "&#x26ce;"                             },
   { ":orange:",                                "&#x1f34a;"                            },
   { ":orange_book:",                           "&#x1f4d9;"                            },
+  { ":orange_circle:",                         "&#x1f7e0;"                            },
+  { ":orange_heart:",                          "&#x1f9e1;"                            },
+  { ":orange_square:",                         "&#x1f7e7;"                            },
+  { ":orangutan:",                             "&#x1f9a7;"                            },
   { ":orthodox_cross:",                        "&#x2626;"                             },
+  { ":otter:",                                 "&#x1f9a6;"                            },
   { ":outbox_tray:",                           "&#x1f4e4;"                            },
   { ":owl:",                                   "&#x1f989;"                            },
   { ":ox:",                                    "&#x1f402;"                            },
+  { ":oyster:",                                "&#x1f9aa;"                            },
   { ":package:",                               "&#x1f4e6;"                            },
   { ":page_facing_up:",                        "&#x1f4c4;"                            },
   { ":page_with_curl:",                        "&#x1f4c3;"                            },
@@ -990,23 +1209,28 @@ static struct emojiEntityInfo
   { ":palau:",                                 "&#x1f1f5;&#x1f1fc;"                   },
   { ":palestinian_territories:",               "&#x1f1f5;&#x1f1f8;"                   },
   { ":palm_tree:",                             "&#x1f334;"                            },
+  { ":palms_up_together:",                     "&#x1f932;"                            },
   { ":panama:",                                "&#x1f1f5;&#x1f1e6;"                   },
   { ":pancakes:",                              "&#x1f95e;"                            },
   { ":panda_face:",                            "&#x1f43c;"                            },
   { ":paperclip:",                             "&#x1f4ce;"                            },
   { ":paperclips:",                            "&#x1f587;"                            },
   { ":papua_new_guinea:",                      "&#x1f1f5;&#x1f1ec;"                   },
+  { ":parachute:",                             "&#x1fa82;"                            },
   { ":paraguay:",                              "&#x1f1f5;&#x1f1fe;"                   },
   { ":parasol_on_ground:",                     "&#x26f1;"                             },
   { ":parking:",                               "&#x1f17f;"                            },
+  { ":parrot:",                                "&#x1f99c;"                            },
   { ":part_alternation_mark:",                 "&#x303d;"                             },
   { ":partly_sunny:",                          "&#x26c5;"                             },
+  { ":partying_face:",                         "&#x1f973;"                            },
   { ":passenger_ship:",                        "&#x1f6f3;"                            },
   { ":passport_control:",                      "&#x1f6c2;"                            },
   { ":pause_button:",                          "&#x23f8;"                             },
   { ":paw_prints:",                            "&#x1f43e;"                            },
   { ":peace_symbol:",                          "&#x262e;"                             },
   { ":peach:",                                 "&#x1f351;"                            },
+  { ":peacock:",                               "&#x1f99a;"                            },
   { ":peanuts:",                               "&#x1f95c;"                            },
   { ":pear:",                                  "&#x1f350;"                            },
   { ":pen:",                                   "&#x1f58a;"                            },
@@ -1014,37 +1238,60 @@ static struct emojiEntityInfo
   { ":pencil2:",                               "&#x270f;"                             },
   { ":penguin:",                               "&#x1f427;"                            },
   { ":pensive:",                               "&#x1f614;"                            },
+  { ":people_holding_hands:",                  "&#x1f9d1;&#x200d;&#x1f91d;&#x200d;&#x1f9d1;" },
+  { ":people_hugging:",                        "&#x1fac2;"                            },
   { ":performing_arts:",                       "&#x1f3ad;"                            },
   { ":persevere:",                             "&#x1f623;"                            },
+  { ":person_bald:",                           "&#x1f9d1;&#x200d;&#x1f9b2;"           },
+  { ":person_curly_hair:",                     "&#x1f9d1;&#x200d;&#x1f9b1;"           },
+  { ":person_feeding_baby:",                   "&#x1f9d1;&#x200d;&#x1f37c;"           },
   { ":person_fencing:",                        "&#x1f93a;"                            },
-  { ":person_frowning:",                       "&#x1f64d;"                            },
-  { ":person_with_blond_hair:",                "&#x1f471;"                            },
-  { ":person_with_pouting_face:",              "&#x1f64e;"                            },
+  { ":person_in_manual_wheelchair:",           "&#x1f9d1;&#x200d;&#x1f9bd;"           },
+  { ":person_in_motorized_wheelchair:",        "&#x1f9d1;&#x200d;&#x1f9bc;"           },
+  { ":person_in_tuxedo:",                      "&#x1f935;"                            },
+  { ":person_red_hair:",                       "&#x1f9d1;&#x200d;&#x1f9b0;"           },
+  { ":person_white_hair:",                     "&#x1f9d1;&#x200d;&#x1f9b3;"           },
+  { ":person_with_probing_cane:",              "&#x1f9d1;&#x200d;&#x1f9af;"           },
+  { ":person_with_turban:",                    "&#x1f473;"                            },
+  { ":person_with_veil:",                      "&#x1f470;"                            },
   { ":peru:",                                  "&#x1f1f5;&#x1f1ea;"                   },
+  { ":petri_dish:",                            "&#x1f9eb;"                            },
   { ":philippines:",                           "&#x1f1f5;&#x1f1ed;"                   },
   { ":phone:",                                 "&#x260e;"                             },
   { ":pick:",                                  "&#x26cf;"                             },
+  { ":pickup_truck:",                          "&#x1f6fb;"                            },
+  { ":pie:",                                   "&#x1f967;"                            },
   { ":pig:",                                   "&#x1f437;"                            },
   { ":pig2:",                                  "&#x1f416;"                            },
   { ":pig_nose:",                              "&#x1f43d;"                            },
   { ":pill:",                                  "&#x1f48a;"                            },
+  { ":pilot:",                                 "&#x1f9d1;&#x200d;&#x2708;&#xfe0f;"    },
+  { ":pinata:",                                "&#x1fa85;"                            },
+  { ":pinched_fingers:",                       "&#x1f90c;"                            },
+  { ":pinching_hand:",                         "&#x1f90f;"                            },
   { ":pineapple:",                             "&#x1f34d;"                            },
   { ":ping_pong:",                             "&#x1f3d3;"                            },
+  { ":pirate_flag:",                           "&#x1f3f4;&#x200d;&#x2620;&#xfe0f;"    },
   { ":pisces:",                                "&#x2653;"                             },
   { ":pitcairn_islands:",                      "&#x1f1f5;&#x1f1f3;"                   },
   { ":pizza:",                                 "&#x1f355;"                            },
+  { ":placard:",                               "&#x1faa7;"                            },
   { ":place_of_worship:",                      "&#x1f6d0;"                            },
   { ":plate_with_cutlery:",                    "&#x1f37d;"                            },
   { ":play_or_pause_button:",                  "&#x23ef;"                             },
+  { ":pleading_face:",                         "&#x1f97a;"                            },
+  { ":plunger:",                               "&#x1faa0;"                            },
   { ":point_down:",                            "&#x1f447;"                            },
   { ":point_left:",                            "&#x1f448;"                            },
   { ":point_right:",                           "&#x1f449;"                            },
   { ":point_up:",                              "&#x261d;"                             },
   { ":point_up_2:",                            "&#x1f446;"                            },
   { ":poland:",                                "&#x1f1f5;&#x1f1f1;"                   },
+  { ":polar_bear:",                            "&#x1f43b;&#x200d;&#x2744;&#xfe0f;"    },
   { ":police_car:",                            "&#x1f693;"                            },
-  { ":policeman:",                             "&#x1f46e;"                            },
-  { ":policewoman:",                           "&#x1f46e;&#x2640;"                    },
+  { ":police_officer:",                        "&#x1f46e;"                            },
+  { ":policeman:",                             "&#x1f46e;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":policewoman:",                           "&#x1f46e;&#x200d;&#x2640;&#xfe0f;"    },
   { ":poodle:",                                "&#x1f429;"                            },
   { ":poop:",                                  "&#x1f4a9;"                            },
   { ":popcorn:",                               "&#x1f37f;"                            },
@@ -1054,23 +1301,29 @@ static struct emojiEntityInfo
   { ":postbox:",                               "&#x1f4ee;"                            },
   { ":potable_water:",                         "&#x1f6b0;"                            },
   { ":potato:",                                "&#x1f954;"                            },
+  { ":potted_plant:",                          "&#x1fab4;"                            },
   { ":pouch:",                                 "&#x1f45d;"                            },
   { ":poultry_leg:",                           "&#x1f357;"                            },
   { ":pound:",                                 "&#x1f4b7;"                            },
   { ":pout:",                                  "&#x1f621;"                            },
   { ":pouting_cat:",                           "&#x1f63e;"                            },
-  { ":pouting_man:",                           "&#x1f64e;&#x2642;"                    },
-  { ":pouting_woman:",                         "&#x1f64e;"                            },
+  { ":pouting_face:",                          "&#x1f64e;"                            },
+  { ":pouting_man:",                           "&#x1f64e;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":pouting_woman:",                         "&#x1f64e;&#x200d;&#x2640;&#xfe0f;"    },
   { ":pray:",                                  "&#x1f64f;"                            },
   { ":prayer_beads:",                          "&#x1f4ff;"                            },
   { ":pregnant_woman:",                        "&#x1f930;"                            },
+  { ":pretzel:",                               "&#x1f968;"                            },
   { ":previous_track_button:",                 "&#x23ee;"                             },
   { ":prince:",                                "&#x1f934;"                            },
   { ":princess:",                              "&#x1f478;"                            },
   { ":printer:",                               "&#x1f5a8;"                            },
+  { ":probing_cane:",                          "&#x1f9af;"                            },
   { ":puerto_rico:",                           "&#x1f1f5;&#x1f1f7;"                   },
   { ":punch:",                                 "&#x1f44a;"                            },
+  { ":purple_circle:",                         "&#x1f7e3;"                            },
   { ":purple_heart:",                          "&#x1f49c;"                            },
+  { ":purple_square:",                         "&#x1f7ea;"                            },
   { ":purse:",                                 "&#x1f45b;"                            },
   { ":pushpin:",                               "&#x1f4cc;"                            },
   { ":put_litter_in_its_place:",               "&#x1f6ae;"                            },
@@ -1078,6 +1331,7 @@ static struct emojiEntityInfo
   { ":question:",                              "&#x2753;"                             },
   { ":rabbit:",                                "&#x1f430;"                            },
   { ":rabbit2:",                               "&#x1f407;"                            },
+  { ":raccoon:",                               "&#x1f99d;"                            },
   { ":racehorse:",                             "&#x1f40e;"                            },
   { ":racing_car:",                            "&#x1f3ce;"                            },
   { ":radio:",                                 "&#x1f4fb;"                            },
@@ -1087,21 +1341,28 @@ static struct emojiEntityInfo
   { ":railway_car:",                           "&#x1f683;"                            },
   { ":railway_track:",                         "&#x1f6e4;"                            },
   { ":rainbow:",                               "&#x1f308;"                            },
-  { ":rainbow_flag:",                          "&#x1f3f3;&#x1f308;"                   },
+  { ":rainbow_flag:",                          "&#x1f3f3;&#xfe0f;&#x200d;&#x1f308;"   },
   { ":raised_back_of_hand:",                   "&#x1f91a;"                            },
+  { ":raised_eyebrow:",                        "&#x1f928;"                            },
   { ":raised_hand:",                           "&#x270b;"                             },
   { ":raised_hand_with_fingers_splayed:",      "&#x1f590;"                            },
   { ":raised_hands:",                          "&#x1f64c;"                            },
   { ":raising_hand:",                          "&#x1f64b;"                            },
-  { ":raising_hand_man:",                      "&#x1f64b;&#x2642;"                    },
-  { ":raising_hand_woman:",                    "&#x1f64b;"                            },
+  { ":raising_hand_man:",                      "&#x1f64b;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":raising_hand_woman:",                    "&#x1f64b;&#x200d;&#x2640;&#xfe0f;"    },
   { ":ram:",                                   "&#x1f40f;"                            },
   { ":ramen:",                                 "&#x1f35c;"                            },
   { ":rat:",                                   "&#x1f400;"                            },
+  { ":razor:",                                 "&#x1fa92;"                            },
+  { ":receipt:",                               "&#x1f9fe;"                            },
   { ":record_button:",                         "&#x23fa;"                             },
   { ":recycle:",                               "&#x267b;"                             },
   { ":red_car:",                               "&#x1f697;"                            },
   { ":red_circle:",                            "&#x1f534;"                            },
+  { ":red_envelope:",                          "&#x1f9e7;"                            },
+  { ":red_haired_man:",                        "&#x1f468;&#x200d;&#x1f9b0;"           },
+  { ":red_haired_woman:",                      "&#x1f469;&#x200d;&#x1f9b0;"           },
+  { ":red_square:",                            "&#x1f7e5;"                            },
   { ":registered:",                            "&#x00ae;"                             },
   { ":relaxed:",                               "&#x263a;"                             },
   { ":relieved:",                              "&#x1f60c;"                            },
@@ -1121,11 +1382,15 @@ static struct emojiEntityInfo
   { ":rice_scene:",                            "&#x1f391;"                            },
   { ":right_anger_bubble:",                    "&#x1f5ef;"                            },
   { ":ring:",                                  "&#x1f48d;"                            },
+  { ":ringed_planet:",                         "&#x1fa90;"                            },
   { ":robot:",                                 "&#x1f916;"                            },
+  { ":rock:",                                  "&#x1faa8;"                            },
   { ":rocket:",                                "&#x1f680;"                            },
   { ":rofl:",                                  "&#x1f923;"                            },
   { ":roll_eyes:",                             "&#x1f644;"                            },
+  { ":roll_of_paper:",                         "&#x1f9fb;"                            },
   { ":roller_coaster:",                        "&#x1f3a2;"                            },
+  { ":roller_skate:",                          "&#x1f6fc;"                            },
   { ":romania:",                               "&#x1f1f7;&#x1f1f4;"                   },
   { ":rooster:",                               "&#x1f413;"                            },
   { ":rose:",                                  "&#x1f339;"                            },
@@ -1133,37 +1398,53 @@ static struct emojiEntityInfo
   { ":rotating_light:",                        "&#x1f6a8;"                            },
   { ":round_pushpin:",                         "&#x1f4cd;"                            },
   { ":rowboat:",                               "&#x1f6a3;"                            },
-  { ":rowing_man:",                            "&#x1f6a3;"                            },
-  { ":rowing_woman:",                          "&#x1f6a3;&#x2640;"                    },
+  { ":rowing_man:",                            "&#x1f6a3;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":rowing_woman:",                          "&#x1f6a3;&#x200d;&#x2640;&#xfe0f;"    },
   { ":ru:",                                    "&#x1f1f7;&#x1f1fa;"                   },
   { ":rugby_football:",                        "&#x1f3c9;"                            },
   { ":runner:",                                "&#x1f3c3;"                            },
   { ":running:",                               "&#x1f3c3;"                            },
-  { ":running_man:",                           "&#x1f3c3;"                            },
+  { ":running_man:",                           "&#x1f3c3;&#x200d;&#x2642;&#xfe0f;"    },
   { ":running_shirt_with_sash:",               "&#x1f3bd;"                            },
-  { ":running_woman:",                         "&#x1f3c3;&#x2640;"                    },
+  { ":running_woman:",                         "&#x1f3c3;&#x200d;&#x2640;&#xfe0f;"    },
   { ":rwanda:",                                "&#x1f1f7;&#x1f1fc;"                   },
   { ":sa:",                                    "&#x1f202;"                            },
+  { ":safety_pin:",                            "&#x1f9f7;"                            },
+  { ":safety_vest:",                           "&#x1f9ba;"                            },
   { ":sagittarius:",                           "&#x2650;"                             },
   { ":sailboat:",                              "&#x26f5;"                             },
   { ":sake:",                                  "&#x1f376;"                            },
+  { ":salt:",                                  "&#x1f9c2;"                            },
   { ":samoa:",                                 "&#x1f1fc;&#x1f1f8;"                   },
   { ":san_marino:",                            "&#x1f1f8;&#x1f1f2;"                   },
   { ":sandal:",                                "&#x1f461;"                            },
+  { ":sandwich:",                              "&#x1f96a;"                            },
   { ":santa:",                                 "&#x1f385;"                            },
   { ":sao_tome_principe:",                     "&#x1f1f8;&#x1f1f9;"                   },
+  { ":sari:",                                  "&#x1f97b;"                            },
+  { ":sassy_man:",                             "&#x1f481;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":sassy_woman:",                           "&#x1f481;&#x200d;&#x2640;&#xfe0f;"    },
   { ":satellite:",                             "&#x1f4e1;"                            },
   { ":satisfied:",                             "&#x1f606;"                            },
   { ":saudi_arabia:",                          "&#x1f1f8;&#x1f1e6;"                   },
+  { ":sauna_man:",                             "&#x1f9d6;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":sauna_person:",                          "&#x1f9d6;"                            },
+  { ":sauna_woman:",                           "&#x1f9d6;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":sauropod:",                              "&#x1f995;"                            },
   { ":saxophone:",                             "&#x1f3b7;"                            },
+  { ":scarf:",                                 "&#x1f9e3;"                            },
   { ":school:",                                "&#x1f3eb;"                            },
   { ":school_satchel:",                        "&#x1f392;"                            },
+  { ":scientist:",                             "&#x1f9d1;&#x200d;&#x1f52c;"           },
   { ":scissors:",                              "&#x2702;"                             },
   { ":scorpion:",                              "&#x1f982;"                            },
   { ":scorpius:",                              "&#x264f;"                             },
+  { ":scotland:",                              "&#x1f3f4;&#xe0067;&#xe0062;&#xe0073;&#xe0063;&#xe0074;&#xe007f;" },
   { ":scream:",                                "&#x1f631;"                            },
   { ":scream_cat:",                            "&#x1f640;"                            },
+  { ":screwdriver:",                           "&#x1fa9b;"                            },
   { ":scroll:",                                "&#x1f4dc;"                            },
+  { ":seal:",                                  "&#x1f9ad;"                            },
   { ":seat:",                                  "&#x1f4ba;"                            },
   { ":secret:",                                "&#x3299;"                             },
   { ":see_no_evil:",                           "&#x1f648;"                            },
@@ -1171,7 +1452,9 @@ static struct emojiEntityInfo
   { ":selfie:",                                "&#x1f933;"                            },
   { ":senegal:",                               "&#x1f1f8;&#x1f1f3;"                   },
   { ":serbia:",                                "&#x1f1f7;&#x1f1f8;"                   },
-  { ":seven:",                                 "&#x0037;&#x20e3;"                     },
+  { ":service_dog:",                           "&#x1f415;&#x200d;&#x1f9ba;"           },
+  { ":seven:",                                 "&#x0037;&#xfe0f;&#x20e3;"             },
+  { ":sewing_needle:",                         "&#x1faa1;"                            },
   { ":seychelles:",                            "&#x1f1f8;&#x1f1e8;"                   },
   { ":shallow_pan_of_food:",                   "&#x1f958;"                            },
   { ":shamrock:",                              "&#x2618;"                             },
@@ -1187,24 +1470,32 @@ static struct emojiEntityInfo
   { ":shoe:",                                  "&#x1f45e;"                            },
   { ":shopping:",                              "&#x1f6cd;"                            },
   { ":shopping_cart:",                         "&#x1f6d2;"                            },
+  { ":shorts:",                                "&#x1fa73;"                            },
   { ":shower:",                                "&#x1f6bf;"                            },
   { ":shrimp:",                                "&#x1f990;"                            },
+  { ":shrug:",                                 "&#x1f937;"                            },
+  { ":shushing_face:",                         "&#x1f92b;"                            },
   { ":sierra_leone:",                          "&#x1f1f8;&#x1f1f1;"                   },
   { ":signal_strength:",                       "&#x1f4f6;"                            },
   { ":singapore:",                             "&#x1f1f8;&#x1f1ec;"                   },
+  { ":singer:",                                "&#x1f9d1;&#x200d;&#x1f3a4;"           },
   { ":sint_maarten:",                          "&#x1f1f8;&#x1f1fd;"                   },
-  { ":six:",                                   "&#x0036;&#x20e3;"                     },
+  { ":six:",                                   "&#x0036;&#xfe0f;&#x20e3;"             },
   { ":six_pointed_star:",                      "&#x1f52f;"                            },
+  { ":skateboard:",                            "&#x1f6f9;"                            },
   { ":ski:",                                   "&#x1f3bf;"                            },
   { ":skier:",                                 "&#x26f7;"                             },
   { ":skull:",                                 "&#x1f480;"                            },
   { ":skull_and_crossbones:",                  "&#x2620;"                             },
+  { ":skunk:",                                 "&#x1f9a8;"                            },
+  { ":sled:",                                  "&#x1f6f7;"                            },
   { ":sleeping:",                              "&#x1f634;"                            },
   { ":sleeping_bed:",                          "&#x1f6cc;"                            },
   { ":sleepy:",                                "&#x1f62a;"                            },
   { ":slightly_frowning_face:",                "&#x1f641;"                            },
   { ":slightly_smiling_face:",                 "&#x1f642;"                            },
   { ":slot_machine:",                          "&#x1f3b0;"                            },
+  { ":sloth:",                                 "&#x1f9a5;"                            },
   { ":slovakia:",                              "&#x1f1f8;&#x1f1f0;"                   },
   { ":slovenia:",                              "&#x1f1f8;&#x1f1ee;"                   },
   { ":small_airplane:",                        "&#x1f6e9;"                            },
@@ -1216,6 +1507,8 @@ static struct emojiEntityInfo
   { ":smile_cat:",                             "&#x1f638;"                            },
   { ":smiley:",                                "&#x1f603;"                            },
   { ":smiley_cat:",                            "&#x1f63a;"                            },
+  { ":smiling_face_with_tear:",                "&#x1f972;"                            },
+  { ":smiling_face_with_three_hearts:",        "&#x1f970;"                            },
   { ":smiling_imp:",                           "&#x1f608;"                            },
   { ":smirk:",                                 "&#x1f60f;"                            },
   { ":smirk_cat:",                             "&#x1f63c;"                            },
@@ -1227,8 +1520,11 @@ static struct emojiEntityInfo
   { ":snowflake:",                             "&#x2744;"                             },
   { ":snowman:",                               "&#x26c4;"                             },
   { ":snowman_with_snow:",                     "&#x2603;"                             },
+  { ":soap:",                                  "&#x1f9fc;"                            },
   { ":sob:",                                   "&#x1f62d;"                            },
   { ":soccer:",                                "&#x26bd;"                             },
+  { ":socks:",                                 "&#x1f9e6;"                            },
+  { ":softball:",                              "&#x1f94e;"                            },
   { ":solomon_islands:",                       "&#x1f1f8;&#x1f1e7;"                   },
   { ":somalia:",                               "&#x1f1f8;&#x1f1f4;"                   },
   { ":soon:",                                  "&#x1f51c;"                            },
@@ -1253,6 +1549,7 @@ static struct emojiEntityInfo
   { ":spider_web:",                            "&#x1f578;"                            },
   { ":spiral_calendar:",                       "&#x1f5d3;"                            },
   { ":spiral_notepad:",                        "&#x1f5d2;"                            },
+  { ":sponge:",                                "&#x1f9fd;"                            },
   { ":spoon:",                                 "&#x1f944;"                            },
   { ":squid:",                                 "&#x1f991;"                            },
   { ":sri_lanka:",                             "&#x1f1f1;&#x1f1f0;"                   },
@@ -1260,17 +1557,23 @@ static struct emojiEntityInfo
   { ":st_helena:",                             "&#x1f1f8;&#x1f1ed;"                   },
   { ":st_kitts_nevis:",                        "&#x1f1f0;&#x1f1f3;"                   },
   { ":st_lucia:",                              "&#x1f1f1;&#x1f1e8;"                   },
+  { ":st_martin:",                             "&#x1f1f2;&#x1f1eb;"                   },
   { ":st_pierre_miquelon:",                    "&#x1f1f5;&#x1f1f2;"                   },
   { ":st_vincent_grenadines:",                 "&#x1f1fb;&#x1f1e8;"                   },
   { ":stadium:",                               "&#x1f3df;"                            },
+  { ":standing_man:",                          "&#x1f9cd;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":standing_person:",                       "&#x1f9cd;"                            },
+  { ":standing_woman:",                        "&#x1f9cd;&#x200d;&#x2640;&#xfe0f;"    },
   { ":star:",                                  "&#x2b50;"                             },
   { ":star2:",                                 "&#x1f31f;"                            },
   { ":star_and_crescent:",                     "&#x262a;"                             },
   { ":star_of_david:",                         "&#x2721;"                             },
+  { ":star_struck:",                           "&#x1f929;"                            },
   { ":stars:",                                 "&#x1f320;"                            },
   { ":station:",                               "&#x1f689;"                            },
   { ":statue_of_liberty:",                     "&#x1f5fd;"                            },
   { ":steam_locomotive:",                      "&#x1f682;"                            },
+  { ":stethoscope:",                           "&#x1fa7a;"                            },
   { ":stew:",                                  "&#x1f372;"                            },
   { ":stop_button:",                           "&#x23f9;"                             },
   { ":stop_sign:",                             "&#x1f6d1;"                            },
@@ -1280,6 +1583,7 @@ static struct emojiEntityInfo
   { ":stuck_out_tongue:",                      "&#x1f61b;"                            },
   { ":stuck_out_tongue_closed_eyes:",          "&#x1f61d;"                            },
   { ":stuck_out_tongue_winking_eye:",          "&#x1f61c;"                            },
+  { ":student:",                               "&#x1f9d1;&#x200d;&#x1f393;"           },
   { ":studio_microphone:",                     "&#x1f399;"                            },
   { ":stuffed_flatbread:",                     "&#x1f959;"                            },
   { ":sudan:",                                 "&#x1f1f8;&#x1f1e9;"                   },
@@ -1292,46 +1596,65 @@ static struct emojiEntityInfo
   { ":sunny:",                                 "&#x2600;"                             },
   { ":sunrise:",                               "&#x1f305;"                            },
   { ":sunrise_over_mountains:",                "&#x1f304;"                            },
+  { ":superhero:",                             "&#x1f9b8;"                            },
+  { ":superhero_man:",                         "&#x1f9b8;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":superhero_woman:",                       "&#x1f9b8;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":supervillain:",                          "&#x1f9b9;"                            },
+  { ":supervillain_man:",                      "&#x1f9b9;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":supervillain_woman:",                    "&#x1f9b9;&#x200d;&#x2640;&#xfe0f;"    },
   { ":surfer:",                                "&#x1f3c4;"                            },
-  { ":surfing_man:",                           "&#x1f3c4;"                            },
-  { ":surfing_woman:",                         "&#x1f3c4;&#x2640;"                    },
+  { ":surfing_man:",                           "&#x1f3c4;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":surfing_woman:",                         "&#x1f3c4;&#x200d;&#x2640;&#xfe0f;"    },
   { ":suriname:",                              "&#x1f1f8;&#x1f1f7;"                   },
   { ":sushi:",                                 "&#x1f363;"                            },
   { ":suspension_railway:",                    "&#x1f69f;"                            },
+  { ":svalbard_jan_mayen:",                    "&#x1f1f8;&#x1f1ef;"                   },
+  { ":swan:",                                  "&#x1f9a2;"                            },
   { ":swaziland:",                             "&#x1f1f8;&#x1f1ff;"                   },
   { ":sweat:",                                 "&#x1f613;"                            },
   { ":sweat_drops:",                           "&#x1f4a6;"                            },
   { ":sweat_smile:",                           "&#x1f605;"                            },
   { ":sweden:",                                "&#x1f1f8;&#x1f1ea;"                   },
   { ":sweet_potato:",                          "&#x1f360;"                            },
+  { ":swim_brief:",                            "&#x1fa72;"                            },
   { ":swimmer:",                               "&#x1f3ca;"                            },
-  { ":swimming_man:",                          "&#x1f3ca;"                            },
-  { ":swimming_woman:",                        "&#x1f3ca;&#x2640;"                    },
+  { ":swimming_man:",                          "&#x1f3ca;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":swimming_woman:",                        "&#x1f3ca;&#x200d;&#x2640;&#xfe0f;"    },
   { ":switzerland:",                           "&#x1f1e8;&#x1f1ed;"                   },
   { ":symbols:",                               "&#x1f523;"                            },
   { ":synagogue:",                             "&#x1f54d;"                            },
   { ":syria:",                                 "&#x1f1f8;&#x1f1fe;"                   },
   { ":syringe:",                               "&#x1f489;"                            },
+  { ":t-rex:",                                 "&#x1f996;"                            },
   { ":taco:",                                  "&#x1f32e;"                            },
   { ":tada:",                                  "&#x1f389;"                            },
   { ":taiwan:",                                "&#x1f1f9;&#x1f1fc;"                   },
   { ":tajikistan:",                            "&#x1f1f9;&#x1f1ef;"                   },
+  { ":takeout_box:",                           "&#x1f961;"                            },
+  { ":tamale:",                                "&#x1fad4;"                            },
   { ":tanabata_tree:",                         "&#x1f38b;"                            },
   { ":tangerine:",                             "&#x1f34a;"                            },
   { ":tanzania:",                              "&#x1f1f9;&#x1f1ff;"                   },
   { ":taurus:",                                "&#x2649;"                             },
   { ":taxi:",                                  "&#x1f695;"                            },
   { ":tea:",                                   "&#x1f375;"                            },
+  { ":teacher:",                               "&#x1f9d1;&#x200d;&#x1f3eb;"           },
+  { ":teapot:",                                "&#x1fad6;"                            },
+  { ":technologist:",                          "&#x1f9d1;&#x200d;&#x1f4bb;"           },
+  { ":teddy_bear:",                            "&#x1f9f8;"                            },
   { ":telephone:",                             "&#x260e;"                             },
   { ":telephone_receiver:",                    "&#x1f4de;"                            },
   { ":telescope:",                             "&#x1f52d;"                            },
   { ":tennis:",                                "&#x1f3be;"                            },
   { ":tent:",                                  "&#x26fa;"                             },
+  { ":test_tube:",                             "&#x1f9ea;"                            },
   { ":thailand:",                              "&#x1f1f9;&#x1f1ed;"                   },
   { ":thermometer:",                           "&#x1f321;"                            },
   { ":thinking:",                              "&#x1f914;"                            },
+  { ":thong_sandal:",                          "&#x1fa74;"                            },
   { ":thought_balloon:",                       "&#x1f4ad;"                            },
-  { ":three:",                                 "&#x0033;&#x20e3;"                     },
+  { ":thread:",                                "&#x1f9f5;"                            },
+  { ":three:",                                 "&#x0033;&#xfe0f;&#x20e3;"             },
   { ":thumbsdown:",                            "&#x1f44e;"                            },
   { ":thumbsup:",                              "&#x1f44d;"                            },
   { ":ticket:",                                "&#x1f3ab;"                            },
@@ -1340,8 +1663,9 @@ static struct emojiEntityInfo
   { ":tiger2:",                                "&#x1f405;"                            },
   { ":timer_clock:",                           "&#x23f2;"                             },
   { ":timor_leste:",                           "&#x1f1f9;&#x1f1f1;"                   },
-  { ":tipping_hand_man:",                      "&#x1f481;&#x2642;"                    },
-  { ":tipping_hand_woman:",                    "&#x1f481;"                            },
+  { ":tipping_hand_man:",                      "&#x1f481;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":tipping_hand_person:",                   "&#x1f481;"                            },
+  { ":tipping_hand_woman:",                    "&#x1f481;&#x200d;&#x2640;&#xfe0f;"    },
   { ":tired_face:",                            "&#x1f62b;"                            },
   { ":tm:",                                    "&#x2122;"                             },
   { ":togo:",                                  "&#x1f1f9;&#x1f1ec;"                   },
@@ -1351,6 +1675,9 @@ static struct emojiEntityInfo
   { ":tomato:",                                "&#x1f345;"                            },
   { ":tonga:",                                 "&#x1f1f9;&#x1f1f4;"                   },
   { ":tongue:",                                "&#x1f445;"                            },
+  { ":toolbox:",                               "&#x1f9f0;"                            },
+  { ":tooth:",                                 "&#x1f9b7;"                            },
+  { ":toothbrush:",                            "&#x1faa5;"                            },
   { ":top:",                                   "&#x1f51d;"                            },
   { ":tophat:",                                "&#x1f3a9;"                            },
   { ":tornado:",                               "&#x1f32a;"                            },
@@ -1361,10 +1688,13 @@ static struct emojiEntityInfo
   { ":train:",                                 "&#x1f68b;"                            },
   { ":train2:",                                "&#x1f686;"                            },
   { ":tram:",                                  "&#x1f68a;"                            },
+  { ":transgender_flag:",                      "&#x1f3f3;&#xfe0f;&#x200d;&#x26a7;&#xfe0f;" },
+  { ":transgender_symbol:",                    "&#x26a7;"                             },
   { ":triangular_flag_on_post:",               "&#x1f6a9;"                            },
   { ":triangular_ruler:",                      "&#x1f4d0;"                            },
   { ":trident:",                               "&#x1f531;"                            },
   { ":trinidad_tobago:",                       "&#x1f1f9;&#x1f1f9;"                   },
+  { ":tristan_da_cunha:",                      "&#x1f1f9;&#x1f1e6;"                   },
   { ":triumph:",                               "&#x1f624;"                            },
   { ":trolleybus:",                            "&#x1f68e;"                            },
   { ":trophy:",                                "&#x1f3c6;"                            },
@@ -1383,7 +1713,7 @@ static struct emojiEntityInfo
   { ":tuvalu:",                                "&#x1f1f9;&#x1f1fb;"                   },
   { ":tv:",                                    "&#x1f4fa;"                            },
   { ":twisted_rightwards_arrows:",             "&#x1f500;"                            },
-  { ":two:",                                   "&#x0032;&#x20e3;"                     },
+  { ":two:",                                   "&#x0032;&#xfe0f;&#x20e3;"             },
   { ":two_hearts:",                            "&#x1f495;"                            },
   { ":two_men_holding_hands:",                 "&#x1f46c;"                            },
   { ":two_women_holding_hands:",               "&#x1f46d;"                            },
@@ -1406,14 +1736,19 @@ static struct emojiEntityInfo
   { ":underage:",                              "&#x1f51e;"                            },
   { ":unicorn:",                               "&#x1f984;"                            },
   { ":united_arab_emirates:",                  "&#x1f1e6;&#x1f1ea;"                   },
+  { ":united_nations:",                        "&#x1f1fa;&#x1f1f3;"                   },
   { ":unlock:",                                "&#x1f513;"                            },
   { ":up:",                                    "&#x1f199;"                            },
   { ":upside_down_face:",                      "&#x1f643;"                            },
   { ":uruguay:",                               "&#x1f1fa;&#x1f1fe;"                   },
   { ":us:",                                    "&#x1f1fa;&#x1f1f8;"                   },
+  { ":us_outlying_islands:",                   "&#x1f1fa;&#x1f1f2;"                   },
   { ":us_virgin_islands:",                     "&#x1f1fb;&#x1f1ee;"                   },
   { ":uzbekistan:",                            "&#x1f1fa;&#x1f1ff;"                   },
   { ":v:",                                     "&#x270c;"                             },
+  { ":vampire:",                               "&#x1f9db;"                            },
+  { ":vampire_man:",                           "&#x1f9db;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":vampire_woman:",                         "&#x1f9db;&#x200d;&#x2640;&#xfe0f;"    },
   { ":vanuatu:",                               "&#x1f1fb;&#x1f1fa;"                   },
   { ":vatican_city:",                          "&#x1f1fb;&#x1f1e6;"                   },
   { ":venezuela:",                             "&#x1f1fb;&#x1f1ea;"                   },
@@ -1427,11 +1762,14 @@ static struct emojiEntityInfo
   { ":virgo:",                                 "&#x264d;"                             },
   { ":volcano:",                               "&#x1f30b;"                            },
   { ":volleyball:",                            "&#x1f3d0;"                            },
+  { ":vomiting_face:",                         "&#x1f92e;"                            },
   { ":vs:",                                    "&#x1f19a;"                            },
   { ":vulcan_salute:",                         "&#x1f596;"                            },
+  { ":waffle:",                                "&#x1f9c7;"                            },
+  { ":wales:",                                 "&#x1f3f4;&#xe0067;&#xe0062;&#xe0077;&#xe006c;&#xe0073;&#xe007f;" },
   { ":walking:",                               "&#x1f6b6;"                            },
-  { ":walking_man:",                           "&#x1f6b6;"                            },
-  { ":walking_woman:",                         "&#x1f6b6;&#x2640;"                    },
+  { ":walking_man:",                           "&#x1f6b6;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":walking_woman:",                         "&#x1f6b6;&#x200d;&#x2640;&#xfe0f;"    },
   { ":wallis_futuna:",                         "&#x1f1fc;&#x1f1eb;"                   },
   { ":waning_crescent_moon:",                  "&#x1f318;"                            },
   { ":waning_gibbous_moon:",                   "&#x1f316;"                            },
@@ -1439,6 +1777,7 @@ static struct emojiEntityInfo
   { ":wastebasket:",                           "&#x1f5d1;"                            },
   { ":watch:",                                 "&#x231a;"                             },
   { ":water_buffalo:",                         "&#x1f403;"                            },
+  { ":water_polo:",                            "&#x1f93d;"                            },
   { ":watermelon:",                            "&#x1f349;"                            },
   { ":wave:",                                  "&#x1f44b;"                            },
   { ":wavy_dash:",                             "&#x3030;"                             },
@@ -1447,8 +1786,9 @@ static struct emojiEntityInfo
   { ":wc:",                                    "&#x1f6be;"                            },
   { ":weary:",                                 "&#x1f629;"                            },
   { ":wedding:",                               "&#x1f492;"                            },
-  { ":weight_lifting_man:",                    "&#x1f3cb;"                            },
-  { ":weight_lifting_woman:",                  "&#x1f3cb;&#x2640;"                    },
+  { ":weight_lifting:",                        "&#x1f3cb;"                            },
+  { ":weight_lifting_man:",                    "&#x1f3cb;&#xfe0f;&#x200d;&#x2642;&#xfe0f;" },
+  { ":weight_lifting_woman:",                  "&#x1f3cb;&#xfe0f;&#x200d;&#x2640;&#xfe0f;" },
   { ":western_sahara:",                        "&#x1f1ea;&#x1f1ed;"                   },
   { ":whale:",                                 "&#x1f433;"                            },
   { ":whale2:",                                "&#x1f40b;"                            },
@@ -1458,6 +1798,9 @@ static struct emojiEntityInfo
   { ":white_circle:",                          "&#x26aa;"                             },
   { ":white_flag:",                            "&#x1f3f3;"                            },
   { ":white_flower:",                          "&#x1f4ae;"                            },
+  { ":white_haired_man:",                      "&#x1f468;&#x200d;&#x1f9b3;"           },
+  { ":white_haired_woman:",                    "&#x1f469;&#x200d;&#x1f9b3;"           },
+  { ":white_heart:",                           "&#x1f90d;"                            },
   { ":white_large_square:",                    "&#x2b1c;"                             },
   { ":white_medium_small_square:",             "&#x25fd;"                             },
   { ":white_medium_square:",                   "&#x25fb;"                             },
@@ -1466,66 +1809,107 @@ static struct emojiEntityInfo
   { ":wilted_flower:",                         "&#x1f940;"                            },
   { ":wind_chime:",                            "&#x1f390;"                            },
   { ":wind_face:",                             "&#x1f32c;"                            },
+  { ":window:",                                "&#x1fa9f;"                            },
   { ":wine_glass:",                            "&#x1f377;"                            },
   { ":wink:",                                  "&#x1f609;"                            },
   { ":wolf:",                                  "&#x1f43a;"                            },
   { ":woman:",                                 "&#x1f469;"                            },
-  { ":woman_artist:",                          "&#x1f469;&#x1f3a8;"                   },
-  { ":woman_astronaut:",                       "&#x1f469;&#x1f680;"                   },
-  { ":woman_cartwheeling:",                    "&#x1f938;&#x2640;"                    },
-  { ":woman_cook:",                            "&#x1f469;&#x1f373;"                   },
-  { ":woman_facepalming:",                     "&#x1f926;&#x2640;"                    },
-  { ":woman_factory_worker:",                  "&#x1f469;&#x1f3ed;"                   },
-  { ":woman_farmer:",                          "&#x1f469;&#x1f33e;"                   },
-  { ":woman_firefighter:",                     "&#x1f469;&#x1f692;"                   },
-  { ":woman_health_worker:",                   "&#x1f469;&#x2695;"                    },
-  { ":woman_judge:",                           "&#x1f469;&#x2696;"                    },
-  { ":woman_juggling:",                        "&#x1f939;&#x2640;"                    },
-  { ":woman_mechanic:",                        "&#x1f469;&#x1f527;"                   },
-  { ":woman_office_worker:",                   "&#x1f469;&#x1f4bc;"                   },
-  { ":woman_pilot:",                           "&#x1f469;&#x2708;"                    },
-  { ":woman_playing_handball:",                "&#x1f93e;&#x2640;"                    },
-  { ":woman_playing_water_polo:",              "&#x1f93d;&#x2640;"                    },
-  { ":woman_scientist:",                       "&#x1f469;&#x1f52c;"                   },
-  { ":woman_shrugging:",                       "&#x1f937;&#x2640;"                    },
-  { ":woman_singer:",                          "&#x1f469;&#x1f3a4;"                   },
-  { ":woman_student:",                         "&#x1f469;&#x1f393;"                   },
-  { ":woman_teacher:",                         "&#x1f469;&#x1f3eb;"                   },
-  { ":woman_technologist:",                    "&#x1f469;&#x1f4bb;"                   },
-  { ":woman_with_turban:",                     "&#x1f473;&#x2640;"                    },
+  { ":woman_artist:",                          "&#x1f469;&#x200d;&#x1f3a8;"           },
+  { ":woman_astronaut:",                       "&#x1f469;&#x200d;&#x1f680;"           },
+  { ":woman_beard:",                           "&#x1f9d4;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":woman_cartwheeling:",                    "&#x1f938;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":woman_cook:",                            "&#x1f469;&#x200d;&#x1f373;"           },
+  { ":woman_dancing:",                         "&#x1f483;"                            },
+  { ":woman_facepalming:",                     "&#x1f926;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":woman_factory_worker:",                  "&#x1f469;&#x200d;&#x1f3ed;"           },
+  { ":woman_farmer:",                          "&#x1f469;&#x200d;&#x1f33e;"           },
+  { ":woman_feeding_baby:",                    "&#x1f469;&#x200d;&#x1f37c;"           },
+  { ":woman_firefighter:",                     "&#x1f469;&#x200d;&#x1f692;"           },
+  { ":woman_health_worker:",                   "&#x1f469;&#x200d;&#x2695;&#xfe0f;"    },
+  { ":woman_in_manual_wheelchair:",            "&#x1f469;&#x200d;&#x1f9bd;"           },
+  { ":woman_in_motorized_wheelchair:",         "&#x1f469;&#x200d;&#x1f9bc;"           },
+  { ":woman_in_tuxedo:",                       "&#x1f935;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":woman_judge:",                           "&#x1f469;&#x200d;&#x2696;&#xfe0f;"    },
+  { ":woman_juggling:",                        "&#x1f939;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":woman_mechanic:",                        "&#x1f469;&#x200d;&#x1f527;"           },
+  { ":woman_office_worker:",                   "&#x1f469;&#x200d;&#x1f4bc;"           },
+  { ":woman_pilot:",                           "&#x1f469;&#x200d;&#x2708;&#xfe0f;"    },
+  { ":woman_playing_handball:",                "&#x1f93e;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":woman_playing_water_polo:",              "&#x1f93d;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":woman_scientist:",                       "&#x1f469;&#x200d;&#x1f52c;"           },
+  { ":woman_shrugging:",                       "&#x1f937;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":woman_singer:",                          "&#x1f469;&#x200d;&#x1f3a4;"           },
+  { ":woman_student:",                         "&#x1f469;&#x200d;&#x1f393;"           },
+  { ":woman_teacher:",                         "&#x1f469;&#x200d;&#x1f3eb;"           },
+  { ":woman_technologist:",                    "&#x1f469;&#x200d;&#x1f4bb;"           },
+  { ":woman_with_headscarf:",                  "&#x1f9d5;"                            },
+  { ":woman_with_probing_cane:",               "&#x1f469;&#x200d;&#x1f9af;"           },
+  { ":woman_with_turban:",                     "&#x1f473;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":woman_with_veil:",                       "&#x1f470;&#x200d;&#x2640;&#xfe0f;"    },
   { ":womans_clothes:",                        "&#x1f45a;"                            },
   { ":womans_hat:",                            "&#x1f452;"                            },
-  { ":women_wrestling:",                       "&#x1f93c;&#x2640;"                    },
+  { ":women_wrestling:",                       "&#x1f93c;&#x200d;&#x2640;&#xfe0f;"    },
   { ":womens:",                                "&#x1f6ba;"                            },
+  { ":wood:",                                  "&#x1fab5;"                            },
+  { ":woozy_face:",                            "&#x1f974;"                            },
   { ":world_map:",                             "&#x1f5fa;"                            },
+  { ":worm:",                                  "&#x1fab1;"                            },
   { ":worried:",                               "&#x1f61f;"                            },
   { ":wrench:",                                "&#x1f527;"                            },
+  { ":wrestling:",                             "&#x1f93c;"                            },
   { ":writing_hand:",                          "&#x270d;"                             },
   { ":x:",                                     "&#x274c;"                             },
+  { ":yarn:",                                  "&#x1f9f6;"                            },
+  { ":yawning_face:",                          "&#x1f971;"                            },
+  { ":yellow_circle:",                         "&#x1f7e1;"                            },
   { ":yellow_heart:",                          "&#x1f49b;"                            },
+  { ":yellow_square:",                         "&#x1f7e8;"                            },
   { ":yemen:",                                 "&#x1f1fe;&#x1f1ea;"                   },
   { ":yen:",                                   "&#x1f4b4;"                            },
   { ":yin_yang:",                              "&#x262f;"                             },
+  { ":yo_yo:",                                 "&#x1fa80;"                            },
   { ":yum:",                                   "&#x1f60b;"                            },
   { ":zambia:",                                "&#x1f1ff;&#x1f1f2;"                   },
+  { ":zany_face:",                             "&#x1f92a;"                            },
   { ":zap:",                                   "&#x26a1;"                             },
-  { ":zero:",                                  "&#x0030;&#x20e3;"                     },
+  { ":zebra:",                                 "&#x1f993;"                            },
+  { ":zero:",                                  "&#x0030;&#xfe0f;&#x20e3;"             },
   { ":zimbabwe:",                              "&#x1f1ff;&#x1f1fc;"                   },
   { ":zipper_mouth_face:",                     "&#x1f910;"                            },
-  { ":zzz:",                                   "&#x1f4a4;"                            }
+  { ":zombie:",                                "&#x1f9df;"                            },
+  { ":zombie_man:",                            "&#x1f9df;&#x200d;&#x2642;&#xfe0f;"    },
+  { ":zombie_woman:",                          "&#x1f9df;&#x200d;&#x2640;&#xfe0f;"    },
+  { ":zzz:",                                   "&#x1f4a4;"                            },
+};
+// compatibility with older versions
+static struct emojiEntityCompatibility
+{
+  const char *oldName;
+  const char *newName;
+} g_emojiCompatibilityEntities[] =
+{
+  {":blonde_man:",                            ":blond_haired_man:"},
+  {":person_frowning:",                       ":frowning_person:"},
+  {":person_with_blond_hair:",                ":blond_haired_person:"},
+  {":person_with_pouting_face:",              ":pouting_face:"},
 };
 
 static const int g_numEmojiEntities = (int)(sizeof(g_emojiEntities)/sizeof(*g_emojiEntities));
+static const int g_numEmojiCompatibilityEntities = (int)(sizeof(g_emojiCompatibilityEntities)/sizeof(*g_emojiCompatibilityEntities));
 
 EmojiEntityMapper *EmojiEntityMapper::s_instance = 0;
 
 EmojiEntityMapper::EmojiEntityMapper()
 {
-  // 2 loops to be able to give precedence to the unicodeName (CLDR)
   for (int i = 0; i < g_numEmojiEntities; i++)
   {
     m_name2symGh.insert(std::make_pair(g_emojiEntities[i].name, i));
   }
+  for (int i = 0; i < g_numEmojiCompatibilityEntities; i++)
+  {
+    int ii = symbol2index(g_emojiCompatibilityEntities[i].newName);
+    if (ii != -1) m_name2symGh.insert(std::make_pair(g_emojiCompatibilityEntities[i].oldName, ii));
+  }
 }
 
 EmojiEntityMapper::~EmojiEntityMapper()
@@ -1570,6 +1954,10 @@ void EmojiEntityMapper::writeEmojiFile(TextStream &t)
   {
     t << g_emojiEntities[i].name << "\n";
   }
+  for (int i = 0; i < g_numEmojiCompatibilityEntities; i++)
+  {
+    t << g_emojiCompatibilityEntities[i].oldName << "\n";
+  }
 }
 
 /*! @brief Access routine to the unicode sequence for the Emoji entity
@@ -1591,5 +1979,3 @@ const char *EmojiEntityMapper::name(int index) const
 {
   return index>=0 && index<g_numEmojiEntities ? g_emojiEntities[index].name : 0;
 }
-
-
index 0c79e01..4a86b4d 100644 (file)
@@ -208,7 +208,7 @@ class DevNullCodeDocInterface : public CodeOutputInterface
                               const QCString &, const SourceLinkInfo &, const SourceLinkInfo &
                              ) override {}
     virtual void writeLineNumber(const QCString &,const QCString &,
-                                 const QCString &,int) override {}
+                                 const QCString &,int,bool) override {}
     virtual void startCodeLine(bool) override {}
     virtual void endCodeLine() override {}
     virtual void startFontClass(const QCString &) override {}
@@ -318,7 +318,7 @@ void FileDefImpl::writeTagFile(TextStream &tagFile)
   tagFile << "  <compound kind=\"file\">\n";
   tagFile << "    <name>" << convertToXML(name()) << "</name>\n";
   tagFile << "    <path>" << convertToXML(getPath()) << "</path>\n";
-  tagFile << "    <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>\n";
+  tagFile << "    <filename>" << addHtmlExtensionIfMissing(getOutputFileBase()) << "</filename>\n";
   for (const auto &ii : m_includeList)
   {
     const FileDef *fd=ii.fileDef;
@@ -876,13 +876,6 @@ void FileDefImpl::writeDocumentation(OutputList &ol)
     ol.enableAll();
   }
 
-  if (Doxygen::searchIndex)
-  {
-    Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
-    Doxygen::searchIndex->addWord(localName(),TRUE);
-  }
-
-
   //---------------------------------------- start flexible part -------------------------------
 
   SrcLangExt lang = getLanguage();
@@ -1077,7 +1070,7 @@ void FileDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentM
           ol.writeString("<a class=\"navtab\" ");
           ol.writeString("href=\"");
           if (createSubDirs) ol.writeString("../../");
-          ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor());
+          ol.writeString(addHtmlExtensionIfMissing(md->getOutputFileBase())+"#"+md->anchor());
           ol.writeString("\">");
           ol.writeString(convertToHtml(md->localName()));
           ol.writeString("</a>");
index f45f36e..ff801f7 100644 (file)
@@ -25,7 +25,7 @@ void FileCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
                const FileDef *      fileDef,
                int                  startLine,
                int                  endLine,
-               bool,                // inlineFragment
+               bool                 inlineFragment,
                const MemberDef *,   // memberDef
                bool                 showLineNumbers,
                const Definition *,  // searchCtx,
@@ -43,7 +43,7 @@ void FileCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
     codeOutIntf.startCodeLine(fileDef != 0 && showLineNumbers);
     if (fileDef != 0 && showLineNumbers)
     {
-      codeOutIntf.writeLineNumber(QCString(),QCString(),QCString(),lineNr);
+      codeOutIntf.writeLineNumber(QCString(),QCString(),QCString(),lineNr,!inlineFragment);
     }
     if (!lineStr.isEmpty()) codeOutIntf.codify(lineStr.data());
     codeOutIntf.endCodeLine();
index 51e3ada..9ddcd17 100644 (file)
 %option noyy_top_state
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -136,10 +140,11 @@ struct fortrancodeYY_state
   const char *  inputString = 0;     //!< the code fragment as text
   yy_size_t     inputPosition = 0;   //!< read offset during parsing
   int           inputLines = 0;      //!< number of line in the code fragment
+  QCString      fileName;
   int           yyLineNr = 0;        //!< current line number
   int           contLineNr = 0;      //!< current, local, line number for continuation determination
   int          *hasContLine = 0;     //!< signals whether or not a line has a continuation line (fixed source form)
-  bool          needsTermination = false;
+  bool          insideCodeLine = false;
   const Definition *searchCtx = 0;
   bool          collectXRefs = false;
   bool          isFixedForm = false;
@@ -217,6 +222,10 @@ static std::mutex g_countFlowKeywordsMutex;
 #undef  YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
+
 %}
 
 IDSYM     [a-z_A-Z0-9]
@@ -258,9 +267,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")
 
 %x Start
 %x SubCall
-%x FuncDef
 %x ClassName
-%x ClassVar
 %x Subprog
 %x DocBlock
 %x Use
@@ -269,7 +276,6 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")
 %x Declaration
 %x DeclarationBinding
 %x DeclContLine
-%x Parameterlist
 %x String
 %x Subprogend
 
@@ -375,6 +381,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")
                                         }
 <*>"import"{BS}/"\n"                    |
 <*>"import"{BS_}                        {
+                                          if(YY_START == String) YY_FTN_REJECT; // ignore in strings
                                           startFontClass(yyscanner,"keywordtype");
                                           codifyLines(yyscanner,yytext);
                                           endFontClass(yyscanner);
@@ -410,6 +417,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")
                                           BEGIN(ClassName);
                                         }
 <*>{LANGUAGE_BIND_SPEC}                 {  //
+                                          if(YY_START == String) YY_FTN_REJECT; // ignore in strings
                                           startFontClass(yyscanner,"keyword");
                                           codifyLines(yyscanner,yytext);
                                           endFontClass(yyscanner);
@@ -720,11 +728,13 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")
                                           endFontClass(yyscanner);
                                         }
 <*>"assignment"/{BS}"("{BS}"="{BS}")"   {
+                                          if(YY_START == String) YY_FTN_REJECT; // ignore in strings
                                           startFontClass(yyscanner,"keyword");
                                           codifyLines(yyscanner,yytext);
                                           endFontClass(yyscanner);
                                         }
 <*>"operator"/{BS}"("[^)]*")"           {
+                                          if(YY_START == String) YY_FTN_REJECT; // ignore in strings
                                           startFontClass(yyscanner,"keyword");
                                           codifyLines(yyscanner,yytext);
                                           endFontClass(yyscanner);
@@ -929,23 +939,27 @@ static void startCodeLine(yyscan_t yyscanner)
       {
         yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
                                 yyextra->currentMemberDef->getOutputFileBase(),
-                                yyextra->currentMemberDef->anchor(),yyextra->yyLineNr);
+                                yyextra->currentMemberDef->anchor(),yyextra->yyLineNr,
+                                !yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
       else if (d->isLinkableInProject())
       {
         yyextra->code->writeLineNumber(d->getReference(),
                                 d->getOutputFileBase(),
-                                QCString(),yyextra->yyLineNr);
+                                QCString(),yyextra->yyLineNr,
+                                !yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
     }
     else
     {
-      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr);
+      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr,
+                                     !yyextra->includeCodeFragment);
     }
   }
   yyextra->code->startCodeLine(yyextra->sourceFileDef);
+  yyextra->insideCodeLine=true;
   if (yyextra->currentFontClass)
   {
     yyextra->code->startFontClass(QCString(yyextra->currentFontClass));
@@ -958,6 +972,7 @@ static void endCodeLine(yyscan_t yyscanner)
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   endFontClass(yyscanner);
   yyextra->code->endCodeLine();
+  yyextra->insideCodeLine=false;
 }
 
 static void nextCodeLine(yyscan_t yyscanner)
@@ -1308,8 +1323,7 @@ static int countLines(yyscan_t yyscanner)
   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++,
-    yyextra->needsTermination=TRUE;
+    count++;
   }
   return count;
 }
@@ -1425,7 +1439,7 @@ void FortranCodeParser::resetCodeParserState()
   yyextra->currentDefinition = 0;
   yyextra->currentMemberDef = 0;
   yyextra->currentFontClass = 0;
-  yyextra->needsTermination = FALSE;
+  yyextra->insideCodeLine = FALSE;
   BEGIN( Start );
 }
 
@@ -1460,6 +1474,7 @@ void FortranCodeParser::parseCode(CodeOutputInterface & codeOutIntf,
   yyextra->code = &codeOutIntf;
   yyextra->inputString   = input.data();
   yyextra->inputPosition = 0;
+  yyextra->fileName      = fileDef ? fileDef->fileName():"";
   yyextra->isFixedForm = recognizeFixedForm(input,p->format);
   yyextra->contLineNr = 1;
   yyextra->hasContLine = NULL;
@@ -1468,7 +1483,7 @@ void FortranCodeParser::parseCode(CodeOutputInterface & codeOutIntf,
     checkContLines(yyscanner,yyextra->inputString);
   }
   yyextra->currentFontClass = 0;
-  yyextra->needsTermination = FALSE;
+  yyextra->insideCodeLine = FALSE;
   yyextra->searchCtx = searchCtx;
   yyextra->collectXRefs = collectXRefs;
   if (startLine!=-1)
@@ -1504,10 +1519,9 @@ void FortranCodeParser::parseCode(CodeOutputInterface & codeOutIntf,
   fortrancodeYYrestart(0, yyscanner);
   BEGIN( Start );
   fortrancodeYYlex(yyscanner);
-  if (yyextra->needsTermination)
+  if (yyextra->insideCodeLine)
   {
-    endFontClass(yyscanner);
-    yyextra->code->endCodeLine();
+    endCodeLine(yyscanner);
   }
   if (isExampleBlock && yyextra->sourceFileDef)
   {
index 328612a..20e30b2 100755 (executable)
 %option extra-type="struct fortranscannerYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -238,6 +242,10 @@ static const char *stateToString(int state);
 //-----------------------------------------------------------------------------
 #undef  YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
+
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
 #define YY_USER_ACTION yyextra->colNr+=(int)yyleng;
 #define INVALID_ENTRY ((Entry*)0x8)
 //-----------------------------------------------------------------------------
@@ -323,7 +331,6 @@ SCOPENAME ({ID}{BS}"::"{BS})*
  /** comment parsing states */
 %x      DocBlock
 %x      DocBackLine
-%x      EndDoc
 
 %x      BlockData
 
index 980130f..4e3150e 100644 (file)
@@ -451,8 +451,7 @@ void FTVHelp::generateTree(TextStream &t, const std::vector<FTVNode*> &nl,int le
       }
       if (srcRef)
       {
-        t << "<a href=\"" << srcRef->getSourceFileBase()
-          << Doxygen::htmlFileExtension
+        t << "<a href=\"" << addHtmlExtensionIfMissing(srcRef->getSourceFileBase())
           << "\">";
       }
       if (n->def && n->def->definitionType()==Definition::TypeGroup)
index 60a0d18..b5cda7b 100644 (file)
@@ -613,7 +613,7 @@ void GroupDefImpl::writeTagFile(TextStream &tagFile)
   tagFile << "  <compound kind=\"group\">\n";
   tagFile << "    <name>" << convertToXML(name()) << "</name>\n";
   tagFile << "    <title>" << convertToXML(m_title) << "</title>\n";
-  tagFile << "    <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>\n";
+  tagFile << "    <filename>" << addHtmlExtensionIfMissing(getOutputFileBase()) << "</filename>\n";
   for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Group))
   {
     switch (lde->kind())
@@ -1119,23 +1119,6 @@ void GroupDefImpl::writeDocumentation(OutputList &ol)
   ol.endHeaderSection();
   ol.startContents();
 
-  if (Doxygen::searchIndex)
-  {
-    Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
-    std::string title = m_title.str();
-    static const reg::Ex re(R"(\a[\w-]*)");
-    reg::Iterator it(title,re);
-    reg::Iterator end;
-    for (; it!=end ; ++it)
-    {
-      const auto &match = *it;
-      std::string matchStr = match.str();
-      Doxygen::searchIndex->addWord(matchStr.c_str(),TRUE);
-    }
-  }
-
-  Doxygen::indexList->addIndexItem(this,0,QCString(),m_title);
-
   //---------------------------------------- start flexible part -------------------------------
 
   SrcLangExt lang=getLanguage();
@@ -1320,7 +1303,7 @@ void GroupDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *current
         ol.writeString("<a class=\"navtab\" ");
         ol.writeString("href=\"");
         if (createSubDirs) ol.writeString("../../");
-        ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor());
+        ol.writeString(addHtmlExtensionIfMissing(md->getOutputFileBase())+"#"+md->anchor());
         ol.writeString("\">");
         ol.writeString(convertToHtml(md->localName()));
         ol.writeString("</a>");
index 8c532ca..00bcfec 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef GROWBUF_H
 #define GROWBUF_H
 
+#include <utility>
 #include <stdlib.h>
 #include <string.h>
 #include <string>
@@ -25,6 +26,7 @@ class GrowBuf
     {
       if (this!=&other)
       {
+        free(m_str);
         m_len = other.m_len;
         m_pos = other.m_pos;
         m_str = (char*)malloc(m_len);
@@ -33,16 +35,18 @@ class GrowBuf
       return *this;
     }
     GrowBuf(GrowBuf &&other)
+      : m_str(std::exchange(other.m_str,(char*)0))
+      , m_pos(std::exchange(other.m_pos,0))
+      , m_len(std::exchange(other.m_len,0))
     {
-      m_len = std::move(other.m_len);
-      m_pos = std::move(other.m_pos);
-      m_str = std::move(other.m_str);
     }
     GrowBuf &operator=(GrowBuf &&other)
     {
-      m_len = std::move(other.m_len);
-      m_pos = std::move(other.m_pos);
-      m_str = std::move(other.m_str);
+      if (this==&other)
+        return *this;
+      m_len = std::exchange(other.m_len,0);
+      m_pos = std::exchange(other.m_pos,0);
+      m_str = std::exchange(other.m_str,(char*)0);
       return *this;
     }
     void reserve(uint size) { if (m_len<size) { m_len = size; m_str = (char*)realloc(m_str,m_len); } }
index 4a70939..d3f5c95 100644 (file)
@@ -141,7 +141,9 @@ static bool mustBeOutsideParagraph(const DocNode *n)
         case DocNode::Kind_Verbatim:
           {
             DocVerbatim *dv = (DocVerbatim*)n;
-            return dv->type()!=DocVerbatim::HtmlOnly || dv->isBlock();
+            DocVerbatim::Type t = dv->type();
+            if (t == DocVerbatim::JavaDocCode || t == DocVerbatim::JavaDocLiteral) return FALSE;
+            return t!=DocVerbatim::HtmlOnly || dv->isBlock();
           }
         case DocNode::Kind_StyleChange:
           return ((DocStyleChange*)n)->style()==DocStyleChange::Preformatted ||
@@ -252,6 +254,15 @@ static QCString htmlAttribsToString(const HtmlAttribList &attribs, QCString *pAl
         result+="=\""+convertToXML(att.value)+"\"";
       }
     }
+    else if (att.name=="open")
+    {
+        // The open attribute is a boolean attribute.
+        // Specifies that the details should be visible (open) to the user
+        // As it is a boolean attribute the initialisation value is of no interest
+        result+=" ";
+        result+=att.name;
+        result+="=\"true\"";
+    }
     else if (att.name=="nowrap") // In XHTML, attribute minimization is forbidden, and the nowrap attribute must be defined as <td nowrap="nowrap">.
     {
         result+=" ";
@@ -266,8 +277,7 @@ static QCString htmlAttribsToString(const HtmlAttribList &attribs, QCString *pAl
 
 HtmlDocVisitor::HtmlDocVisitor(TextStream &t,CodeOutputInterface &ci,
                                const Definition *ctx)
-  : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_insidePre(FALSE),
-                                 m_hide(FALSE), m_ctx(ctx)
+  : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_ctx(ctx)
 {
   if (ctx) m_langExt=ctx->getDefFileExtension();
 }
@@ -308,14 +318,22 @@ void HtmlDocVisitor::visit(DocWhiteSpace *w)
 void HtmlDocVisitor::visit(DocSymbol *s)
 {
   if (m_hide) return;
-  const char *res = HtmlEntityMapper::instance()->html(s->symbol());
-  if (res)
+  if (m_insideTitle &&
+      (s->symbol()==DocSymbol::Sym_Quot || s->symbol()==DocSymbol::Sym_quot)) // escape "'s inside title="..."
   {
-    m_t << res;
+    m_t << "&quot;";
   }
   else
   {
-    err("HTML: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s->symbol(),TRUE));
+    const char *res = HtmlEntityMapper::instance()->html(s->symbol());
+    if (res)
+    {
+      m_t << res;
+    }
+    else
+    {
+      err("HTML: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s->symbol(),TRUE));
+    }
   }
 }
 
@@ -335,16 +353,30 @@ void HtmlDocVisitor::visit(DocEmoji *s)
 
 void HtmlDocVisitor::writeObfuscatedMailAddress(const QCString &url)
 {
-  m_t << "<a href=\"#\" onclick=\"location.href='mai'+'lto:'";
-  uint i;
-  int size=3;
-  for (i=0;i<url.length();)
+  if (!Config_getBool(OBFUSCATE_EMAILS))
+  {
+    m_t << "<a href=\"mailto:" << url << "\">";
+  }
+  else
   {
-    m_t << "+'" << url.mid(i,size) << "'";
-    i+=size;
-    if (size==3) size=2; else size=3;
+    m_t << "<a href=\"#\" onclick=\"location.href='mai'+'lto:'";
+    if (!url.isEmpty())
+    {
+      const char *p = url.data();
+      uint size=3;
+      while (*p)
+      {
+        m_t << "+'";
+        for (uint j=0;j<size && *p;j++)
+        {
+          p = writeUTF8Char(m_t,p);
+        }
+        m_t << "'";
+        if (size==3) size=2; else size=3;
+      }
+    }
+    m_t << "; return false;\">";
   }
-  m_t << "; return false;\">";
 }
 
 void HtmlDocVisitor::visit(DocURL *u)
@@ -353,14 +385,26 @@ void HtmlDocVisitor::visit(DocURL *u)
   if (u->isEmail()) // mail address
   {
     QCString url = u->url();
+    // obfuscate the mail address link
     writeObfuscatedMailAddress(url);
-    uint size=5,i;
-    for (i=0;i<url.length();)
+    if (!Config_getBool(OBFUSCATE_EMAILS))
+    {
+      m_t << url;
+    }
+    else
     {
-      filter(url.mid(i,size));
-      if (i<url.length()-size) m_t << "<span style=\"display: none;\">.nosp@m.</span>";
-      i+=size;
-      if (size==5) size=4; else size=5;
+      const char *p = url.data();
+      // also obfuscate the address as shown on the web page
+      uint size=5;
+      while (*p)
+      {
+        for (uint j=0;j<size && *p;j++)
+        {
+          p = writeUTF8Char(m_t,p);
+        }
+        if (*p) m_t << "<span class=\"obfuscator\">.nosp@m.</span>";
+        if (size==5) size=4; else size=5;
+      }
     }
     m_t << "</a>";
   }
@@ -437,6 +481,9 @@ void HtmlDocVisitor::visit(DocStyleChange *s)
     case DocStyleChange::Small:
       if (s->enable()) m_t << "<small" << htmlAttribsToString(s->attribs()) << ">";  else m_t << "</small>";
       break;
+    case DocStyleChange::Cite:
+      if (s->enable()) m_t << "<cite" << htmlAttribsToString(s->attribs()) << ">";  else m_t << "</cite>";
+      break;
     case DocStyleChange::Preformatted:
       if (s->enable())
       {
@@ -466,7 +513,12 @@ void HtmlDocVisitor::visit(DocStyleChange *s)
     case DocStyleChange::Span:
       if (s->enable()) m_t << "<span" << htmlAttribsToString(s->attribs()) << ">";  else m_t << "</span>";
       break;
-
+    case DocStyleChange::Details:
+      if (s->enable()) m_t << "<details" << htmlAttribsToString(s->attribs()) << ">\n"; else m_t << "</details>\n";
+      break;
+    case DocStyleChange::Summary:
+      if (s->enable()) m_t << "<summary" << htmlAttribsToString(s->attribs()) << ">";  else m_t << "</summary>";
+      break;
   }
 }
 
@@ -532,6 +584,14 @@ void HtmlDocVisitor::visit(DocVerbatim *s)
       m_t << "</pre>";
       forceStartParagraph(s);
       break;
+    case DocVerbatim::JavaDocLiteral:
+      filter(s->text(), true);
+      break;
+    case DocVerbatim::JavaDocCode:
+      m_t << "<code class=\"JavaDocCode\">";
+      filter(s->text(), true);
+      m_t << "</code>";
+      break;
     case DocVerbatim::HtmlOnly:
       {
         if (s->isBlock()) forceEndParagraph(s);
@@ -874,7 +934,7 @@ void HtmlDocVisitor::visit(DocFormula *f)
     filterQuotedCdataAttr(f->text());
     m_t << "\"";
     m_t << " src=\"" << f->relPath() << f->name();
-    if (Config_getEnum(HTML_FORMULA_FORMAT)=="svg")
+    if (Config_getEnum(HTML_FORMULA_FORMAT)==HTML_FORMULA_FORMAT_t::svg)
     {
       m_t << ".svg";
     }
@@ -1745,6 +1805,7 @@ void HtmlDocVisitor::visitPre(DocImage *img)
       if (inlineImage)
       {
         m_t << " title=\"";
+        m_insideTitle=true;
       }
       else
       {
@@ -1774,6 +1835,7 @@ void HtmlDocVisitor::visitPost(DocImage *img)
       if (inlineImage)
       {
         m_t << "\"/>";
+        m_insideTitle=false;
       }
       else // end <div class="caption">
       {
@@ -1795,6 +1857,7 @@ void HtmlDocVisitor::visitPost(DocImage *img)
 void HtmlDocVisitor::visitPre(DocDotFile *df)
 {
   if (m_hide) return;
+  if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df->file()));
   m_t << "<div class=\"dotgraph\">\n";
   writeDotFile(df->file(),df->relPath(),df->context(),df->srcFile(),df->srcLine());
   if (df->hasCaption())
@@ -1816,6 +1879,7 @@ void HtmlDocVisitor::visitPost(DocDotFile *df)
 void HtmlDocVisitor::visitPre(DocMscFile *df)
 {
   if (m_hide) return;
+  if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df->file()));
   m_t << "<div class=\"mscgraph\">\n";
   writeMscFile(df->file(),df->relPath(),df->context(),df->srcFile(),df->srcLine());
   if (df->hasCaption())
@@ -1836,6 +1900,7 @@ void HtmlDocVisitor::visitPost(DocMscFile *df)
 void HtmlDocVisitor::visitPre(DocDiaFile *df)
 {
   if (m_hide) return;
+  if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df->file()));
   m_t << "<div class=\"diagraph\">\n";
   writeDiaFile(df->file(),df->relPath(),df->context(),df->srcFile(),df->srcLine());
   if (df->hasCaption())
@@ -2148,7 +2213,7 @@ void HtmlDocVisitor::visitPost(DocParBlock *)
 
 
 
-void HtmlDocVisitor::filter(const QCString &str)
+void HtmlDocVisitor::filter(const QCString &str, const bool retainNewline)
 {
   if (str.isEmpty()) return;
   const char *p=str.data();
@@ -2158,6 +2223,7 @@ void HtmlDocVisitor::filter(const QCString &str)
     c=*p++;
     switch(c)
     {
+      case '\n': if(retainNewline) m_t << "<br/>"; m_t << c; break;
       case '<':  m_t << "&lt;"; break;
       case '>':  m_t << "&gt;"; break;
       case '&':  m_t << "&amp;"; break;
index 4dc7941..46bbec7 100644 (file)
@@ -139,7 +139,7 @@ class HtmlDocVisitor : public DocVisitor
     //--------------------------------------
 
     void writeObfuscatedMailAddress(const QCString &url);
-    void filter(const QCString &str);
+    void filter(const QCString &str, const bool retainNewline = false);
     void filterQuotedCdataAttr(const QCString &str);
     void startLink(const QCString &ref,const QCString &file,
                    const QCString &relPath,const QCString &anchor,
@@ -163,8 +163,9 @@ class HtmlDocVisitor : public DocVisitor
 
     TextStream &m_t;
     CodeOutputInterface &m_ci;
-    bool m_insidePre;
-    bool m_hide;
+    bool m_insidePre = false;
+    bool m_hide = false;
+    bool m_insideTitle = false;
     const Definition *m_ctx;
     QCString m_langExt;
 };
index c9c8b93..bd7e6a4 100644 (file)
@@ -332,7 +332,7 @@ static QCString substituteHtmlKeywords(const QCString &str,
   bool searchEngine = Config_getBool(SEARCHENGINE);
   bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH);
   bool mathJax = Config_getBool(USE_MATHJAX);
-  QCString mathJaxFormat = Config_getEnum(MATHJAX_FORMAT);
+  QCString mathJaxFormat = Config_getEnumAsString(MATHJAX_FORMAT);
   bool disableIndex = Config_getBool(DISABLE_INDEX);
   bool hasProjectName = !projectName.isEmpty();
   bool hasProjectNumber = !Config_getString(PROJECT_NUMBER).isEmpty();
@@ -440,93 +440,97 @@ static QCString substituteHtmlKeywords(const QCString &str,
 
   if (mathJax)
   {
-    QCString mathJaxVersion = Config_getEnum(MATHJAX_VERSION);
+    auto mathJaxVersion = Config_getEnum(MATHJAX_VERSION);
     QCString path = Config_getString(MATHJAX_RELPATH);
     if (path.isEmpty() || path.left(2)=="..") // relative path
     {
       path.prepend(relPath);
     }
 
-    if (mathJaxVersion == "MathJax_3")
+    switch (mathJaxVersion)
     {
-       mathJaxJs += "<script src=\"https://polyfill.io/v3/polyfill.min.js?features=es6\"></script>\n"
-                    "<script type=\"text/javascript\">\n"
-                    "window.MathJax = {\n"
-                    "  options: {\n"
-                    "    ignoreHtmlClass: 'tex2jax_ignore',\n"
-                    "    processHtmlClass: 'tex2jax_process'\n"
-                    "  }";
-      const StringVector &mathJaxExtensions = Config_getList(MATHJAX_EXTENSIONS);
-      if (!mathJaxExtensions.empty() || !g_latex_macro.isEmpty())
-      {
-        mathJaxJs+= ",\n"
-                    "  tex: {\n"
-                    "    macros: {";
-        if (!g_latex_macro.isEmpty())
-        {
-          mathJaxJs += g_latex_macro+"    ";
-        }
-        mathJaxJs+="},\n"
-                    "    packages: ['base','configmacros'";
-        if (!g_latex_macro.isEmpty())
+      case MATHJAX_VERSION_t::MathJax_3:
         {
-          mathJaxJs+= ",'newcommand'";
+          mathJaxJs += "<script src=\"https://polyfill.io/v3/polyfill.min.js?features=es6\"></script>\n"
+                       "<script type=\"text/javascript\">\n"
+                       "window.MathJax = {\n"
+                       "  options: {\n"
+                       "    ignoreHtmlClass: 'tex2jax_ignore',\n"
+                       "    processHtmlClass: 'tex2jax_process'\n"
+                       "  }";
+         const StringVector &mathJaxExtensions = Config_getList(MATHJAX_EXTENSIONS);
+         if (!mathJaxExtensions.empty() || !g_latex_macro.isEmpty())
+         {
+           mathJaxJs+= ",\n"
+                       "  tex: {\n"
+                       "    macros: {";
+           if (!g_latex_macro.isEmpty())
+           {
+             mathJaxJs += g_latex_macro+"    ";
+           }
+           mathJaxJs+="},\n"
+                       "    packages: ['base','configmacros'";
+           if (!g_latex_macro.isEmpty())
+           {
+             mathJaxJs+= ",'newcommand'";
+           }
+           for (const auto &s : mathJaxExtensions)
+           {
+             mathJaxJs+= ",'"+QCString(s.c_str())+"'";
+           }
+           mathJaxJs += "]\n"
+                         "  }\n";
+         }
+         else
+         {
+           mathJaxJs += "\n";
+         }
+         mathJaxJs += "};\n";
+         // MATHJAX_CODEFILE
+         if (!g_mathjax_code.isEmpty())
+         {
+           mathJaxJs += g_mathjax_code;
+           mathJaxJs += "\n";
+         }
+         mathJaxJs += "</script>\n";
+         mathJaxJs += "<script type=\"text/javascript\" id=\"MathJax-script\" async=\"async\" src=\"" +
+                      path + "es5/tex-" + mathJaxFormat.lower() + ".js\">";
+         mathJaxJs+="</script>\n";
         }
-        for (const auto &s : mathJaxExtensions)
+        break;
+      case MATHJAX_VERSION_t::MathJax_2:
         {
-          mathJaxJs+= ",'"+QCString(s.c_str())+"'";
+          mathJaxJs = "<script type=\"text/x-mathjax-config\">\n"
+                      "MathJax.Hub.Config({\n"
+                      "  extensions: [\"tex2jax.js\"";
+          const StringVector &mathJaxExtensions = Config_getList(MATHJAX_EXTENSIONS);
+          for (const auto &s : mathJaxExtensions)
+          {
+            mathJaxJs+= ", \""+QCString(s.c_str())+".js\"";
+          }
+          if (mathJaxFormat.isEmpty())
+          {
+            mathJaxFormat = "HTML-CSS";
+          }
+          mathJaxJs += "],\n"
+                       "  jax: [\"input/TeX\",\"output/"+mathJaxFormat+"\"],\n";
+          if (!g_latex_macro.isEmpty())
+          {
+            mathJaxJs += "   TeX: { Macros: {\n";
+            mathJaxJs += g_latex_macro;
+            mathJaxJs += "\n"
+                         "  } }\n";
+          }
+          mathJaxJs +=   "});\n";
+          if (!g_mathjax_code.isEmpty())
+          {
+            mathJaxJs += g_mathjax_code;
+            mathJaxJs += "\n";
+          }
+          mathJaxJs += "</script>\n";
+          mathJaxJs += "<script type=\"text/javascript\" async=\"async\" src=\"" + path + "MathJax.js\"></script>\n";
         }
-        mathJaxJs += "]\n"
-                      "  }\n";
-      }
-      else
-      {
-        mathJaxJs += "\n";
-      }
-      mathJaxJs += "};\n";
-      // MATHJAX_CODEFILE
-      if (!g_mathjax_code.isEmpty())
-      {
-        mathJaxJs += g_mathjax_code;
-        mathJaxJs += "\n";
-      }
-      mathJaxJs += "</script>\n";
-
-      mathJaxJs += "<script type=\"text/javascript\" id=\"MathJax-script\" async=\"async\" src=\"" +
-                   path + "es5/tex-" + mathJaxFormat.lower() + ".js\">";
-      mathJaxJs+="</script>\n";
-    }
-    else // MathJax v2
-    {
-      mathJaxJs = "<script type=\"text/x-mathjax-config\">\n"
-                  "MathJax.Hub.Config({\n"
-                  "  extensions: [\"tex2jax.js\"";
-      const StringVector &mathJaxExtensions = Config_getList(MATHJAX_EXTENSIONS);
-      for (const auto &s : mathJaxExtensions)
-      {
-        mathJaxJs+= ", \""+QCString(s.c_str())+".js\"";
-      }
-      if (mathJaxFormat.isEmpty())
-      {
-        mathJaxFormat = "HTML-CSS";
-      }
-      mathJaxJs += "],\n"
-                   "  jax: [\"input/TeX\",\"output/"+mathJaxFormat+"\"],\n";
-      if (!g_latex_macro.isEmpty())
-      {
-        mathJaxJs += "   TeX: { Macros: {\n";
-        mathJaxJs += g_latex_macro;
-        mathJaxJs += "\n"
-                     "  } }\n";
-      }
-      mathJaxJs +=   "});\n";
-      if (!g_mathjax_code.isEmpty())
-      {
-        mathJaxJs += g_mathjax_code;
-        mathJaxJs += "\n";
-      }
-      mathJaxJs += "</script>\n";
-      mathJaxJs += "<script type=\"text/javascript\" async=\"async\" src=\"" + path + "MathJax.js\"></script>\n";
+        break;
     }
   }
 
@@ -692,7 +696,7 @@ void HtmlCodeGenerator::docify(const QCString &str)
 }
 
 void HtmlCodeGenerator::writeLineNumber(const QCString &ref,const QCString &filename,
-                                    const QCString &anchor,int l)
+                                    const QCString &anchor,int l,bool writeLineAnchor)
 {
   const int maxLineNrStr = 10;
   char lineNumber[maxLineNrStr];
@@ -706,7 +710,8 @@ void HtmlCodeGenerator::writeLineNumber(const QCString &ref,const QCString &file
     m_lineOpen = TRUE;
   }
 
-  m_t << "<a id=\"" << lineAnchor << "\" name=\"" << lineAnchor << "\"></a><span class=\"lineno\">";
+  if (writeLineAnchor) m_t << "<a id=\"" << lineAnchor << "\" name=\"" << lineAnchor << "\"></a>";
+  m_t << "<span class=\"lineno\">";
   if (!filename.isEmpty())
   {
     _writeCodeLink("line",ref,filename,anchor,lineNumber,QCString());
@@ -1019,6 +1024,7 @@ void HtmlGenerator::writeTabData()
   mgr.copyResource("nav_f.lum",dname);
   mgr.copyResource("bc_s.luma",dname);
   mgr.copyResource("doxygen.svg",dname);
+  Doxygen::indexList->addImageFile("doxygen.svg");
   mgr.copyResource("closed.luma",dname);
   mgr.copyResource("open.luma",dname);
   mgr.copyResource("bdwn.luma",dname);
@@ -1032,6 +1038,7 @@ void HtmlGenerator::writeTabData()
   //  img.save(dname+"/nav_g.png");
   //}
   mgr.copyResource("nav_g.png",dname);
+  Doxygen::indexList->addImageFile("nav_g.png");
 }
 
 void HtmlGenerator::writeSearchData(const QCString &dname)
index a4eefed..d5f7904 100644 (file)
@@ -38,7 +38,7 @@ class HtmlCodeGenerator : public CodeOutputInterface
                       const SourceLinkInfo &defInfo,
                       const SourceLinkInfo &declInfo
                      );
-    void writeLineNumber(const QCString &,const QCString &,const QCString &,int);
+    void writeLineNumber(const QCString &,const QCString &,const QCString &,int, bool);
     void startCodeLine(bool);
     void endCodeLine();
     void startFontClass(const QCString &s);
@@ -95,8 +95,8 @@ class HtmlGenerator : public OutputGenerator
                        const QCString &anchor,const QCString &name,
                        const QCString &tooltip)
     { m_codeGen.writeCodeLink(type,ref,file,anchor,name,tooltip); }
-    void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor,int lineNumber)
-    { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber); }
+    void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor,int lineNumber, bool writeLineAnchor)
+    { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber,writeLineAnchor); }
     void writeTooltip(const QCString &id, const DocLinkInfo &docInfo, const QCString &decl,
                       const QCString &desc, const SourceLinkInfo &defInfo, const SourceLinkInfo &declInfo
                      )
index c86816b..16bd5c0 100644 (file)
@@ -174,7 +174,7 @@ void HtmlHelpIndex::addItem(const QCString &level1,const QCString &level2,
 
 static QCString field2URL(const IndexField *f,bool checkReversed)
 {
-  QCString result = f->url + Doxygen::htmlFileExtension;
+  QCString result = addHtmlExtensionIfMissing(f->url);
   if (!f->anchor.isEmpty() && (!checkReversed || f->reversed))
   {
     // HTML Help needs colons in link anchors to be escaped in the .hhk file.
@@ -555,7 +555,7 @@ void HtmlHelp::Private::createProjectFile()
     }
     for (auto &s : imageFiles)
     {
-      t << FileInfo(s).fileName() << "\n";
+      t << s.c_str() << "\n";
     }
     t.close();
   }
@@ -636,6 +636,7 @@ void HtmlHelp::addContentsItem(bool isDir,
                                bool /* addToNavIndex */,
                                const Definition * /* def */)
 {
+  static bool binaryTOC = Config_getBool(BINARY_TOC);
   // If we're using a binary toc then folders cannot have links.
   // Tried this and I didn't see any problems, when not using
   // the resetting of file and anchor the TOC works better
@@ -657,14 +658,18 @@ void HtmlHelp::addContentsItem(bool isDir,
       if (file[0]=='^') p->cts << "URL"; else p->cts << "Local";
       p->cts << "\" value=\"";
       p->cts << &file[1];
+      p->cts << "\">";
     }
     else
     {
-      p->cts << "<param name=\"Local\" value=\"";
-      p->cts << file << Doxygen::htmlFileExtension;
-      if (!anchor.isEmpty()) p->cts << "#" << anchor;
+      if (!(binaryTOC && isDir))
+      {
+        p->cts << "<param name=\"Local\" value=\"";
+        p->cts << addHtmlExtensionIfMissing(file);
+        if (!anchor.isEmpty()) p->cts << "#" << anchor;
+        p->cts << "\">";
+      }
     }
-    p->cts << "\">";
   }
   p->cts << "<param name=\"ImageNumber\" value=\"";
   if (isDir)  // added - KPW
index 5db1dd9..8e4fb8a 100644 (file)
@@ -721,16 +721,12 @@ static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex)
     ol.pushGeneratorState();
     ol.disable(OutputGenerator::Html);
   }
-  bool fullPathNames = Config_getBool(FULL_PATH_NAMES);
   startIndexHierarchy(ol,0);
-  if (fullPathNames)
+  for (const auto &dd : *Doxygen::dirLinkedMap)
   {
-    for (const auto &dd : *Doxygen::dirLinkedMap)
+    if (dd->getOuterScope()==Doxygen::globalScope)
     {
-      if (dd->getOuterScope()==Doxygen::globalScope)
-      {
-        writeDirTreeNode(ol,dd.get(),0,ftv,addToIndex);
-      }
+      writeDirTreeNode(ol,dd.get(),0,ftv,addToIndex);
     }
   }
   if (ftv)
@@ -739,7 +735,7 @@ static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex)
     {
       for (const auto &fd : *fn)
       {
-        if (!fullPathNames || fd->getDirDef()==0) // top level file
+        if (fd->getDirDef()==0) // top level file
         {
           bool src;
           bool doc = fileVisibleInIndex(fd.get(),src);
@@ -4145,12 +4141,12 @@ static void writeConceptRootList(FTVHelp *ftv,bool addToIndex)
       //printf("*** adding %s hasSubPages=%d hasSections=%d\n",qPrint(pageTitle),hasSubPages,hasSections);
       ftv->addContentsItem(
           false,cd->localName(),cd->getReference(),cd->getOutputFileBase(),
-          QCString(),false,true,cd.get());
+          QCString(),false,cd->partOfGroups().empty(),cd.get());
       if (addToIndex)
       {
         Doxygen::indexList->addContentsItem(
             false,cd->localName(),cd->getReference(),cd->getOutputFileBase(),
-            QCString(),false,true);
+            QCString(),false,cd->partOfGroups().empty(),cd.get());
       }
     }
   }
@@ -4932,7 +4928,7 @@ static void writeIndexHierarchyEntries(OutputList &ol,const LayoutNavEntryList &
             QCString url = correctURL(lne->url(),"!"); // add ! to relative URL
             if (!url.isEmpty())
             {
-              if (url=="![none]")
+              if (url=="!") // result of a "[none]" url
               {
                 Doxygen::indexList->addContentsItem(TRUE,lne->title(),QCString(),QCString(),QCString(),FALSE,FALSE);
               }
index c7cf204..20259c1 100644 (file)
 #endif
 #endif // !ENGLISH_ONLY
 
-#define L_EQUAL(a) !qstricmp(langName.data(),a)
-
 Translator *theTranslator=0;
 
-bool setTranslator(const QCString &langName)
+void setTranslator(OUTPUT_LANGUAGE_t langName)
 {
-  if (L_EQUAL("english"))
+  switch (langName)
   {
-    theTranslator=new TranslatorEnglish;
-  }
+    case OUTPUT_LANGUAGE_t::English:             theTranslator = new TranslatorEnglish; break;
 #if !defined(ENGLISH_ONLY)
-#ifdef LANG_NL
-  else if (L_EQUAL("dutch"))
-  {
-    theTranslator=new TranslatorDutch;
-  }
+#ifdef LANG_ZA
+    case OUTPUT_LANGUAGE_t::Afrikaans:           theTranslator = new TranslatorAfrikaans; break;
+#endif
+#ifdef LANG_AR
+    case OUTPUT_LANGUAGE_t::Arabic:              theTranslator = new TranslatorArabic; break;
 #endif
 #ifdef LANG_AM
-  else if (L_EQUAL("armenian"))
-  {
-    theTranslator=new TranslatorArmenian;
-  }
+    case OUTPUT_LANGUAGE_t::Armenian:            theTranslator = new TranslatorArmenian; break;
 #endif
-#ifdef LANG_SV
-  else if (L_EQUAL("swedish"))
-  {
-    theTranslator=new TranslatorSwedish;
-  }
+#ifdef LANG_BR
+    case OUTPUT_LANGUAGE_t::Brazilian:           theTranslator = new TranslatorBrazilian; break;
 #endif
-#ifdef LANG_CZ
-  else if (L_EQUAL("czech"))
-  {
-    theTranslator=new TranslatorCzech;
-  }
+#ifdef LANG_CA
+    case OUTPUT_LANGUAGE_t::Catalan:             theTranslator = new TranslatorCatalan; break;
 #endif
-#ifdef LANG_FR
-  else if (L_EQUAL("french"))
-  {
-    theTranslator=new TranslatorFrench;
-  }
+#ifdef LANG_CN
+    case OUTPUT_LANGUAGE_t::Chinese:             theTranslator = new TranslatorChinese; break;
 #endif
-#ifdef LANG_ID
-  else if (L_EQUAL("indonesian"))
-  {
-    theTranslator=new TranslatorIndonesian;
-  }
+#ifdef LANG_TW
+    case OUTPUT_LANGUAGE_t::Chinese_Traditional: theTranslator = new TranslatorChinesetraditional; break;
 #endif
-#ifdef LANG_IT
-  else if (L_EQUAL("italian"))
-  {
-    theTranslator=new TranslatorItalian;
-  }
+#ifdef LANG_HR
+    case OUTPUT_LANGUAGE_t::Croatian:            theTranslator = new TranslatorCroatian; break;
 #endif
-#ifdef LANG_DE
-  else if (L_EQUAL("german"))
-  {
-    theTranslator=new TranslatorGerman;
-  }
+#ifdef LANG_CZ
+    case OUTPUT_LANGUAGE_t::Czech:               theTranslator = new TranslatorCzech; break;
 #endif
-#ifdef LANG_JP
-  else if (L_EQUAL("japanese"))
-  {
-    theTranslator=new TranslatorJapanese;
-  }
+#ifdef LANG_DK
+    case OUTPUT_LANGUAGE_t::Danish:              theTranslator = new TranslatorDanish; break;
 #endif
-#ifdef LANG_JE
-  else if (L_EQUAL("japanese-en"))
-  {
-    theTranslator=new TranslatorJapaneseEn;
-  }
+#ifdef LANG_NL
+    case OUTPUT_LANGUAGE_t::Dutch:               theTranslator = new TranslatorDutch; break;
 #endif
-#ifdef LANG_ES
-  else if (L_EQUAL("spanish"))
-  {
-    theTranslator=new TranslatorSpanish;
-  }
+#ifdef LANG_EO
+    case OUTPUT_LANGUAGE_t::Esperanto:           theTranslator = new TranslatorEsperanto; break;
 #endif
-#ifdef LANG_FI
-  else if (L_EQUAL("finnish"))
-  {
-    theTranslator=new TranslatorFinnish;
-  }
+#ifdef LANG_FA
+    case OUTPUT_LANGUAGE_t::Farsi:               theTranslator = new TranslatorPersian; break;
 #endif
-#ifdef LANG_RU
-  else if (L_EQUAL("russian"))
-  {
-    theTranslator=new TranslatorRussian;
-  }
+#ifdef LANG_FI
+    case OUTPUT_LANGUAGE_t::Finnish:             theTranslator = new TranslatorFinnish; break;
 #endif
-#ifdef LANG_HR
-  else if (L_EQUAL("croatian"))
-  {
-    theTranslator=new TranslatorCroatian;
-  }
+#ifdef LANG_FR
+    case OUTPUT_LANGUAGE_t::French:              theTranslator = new TranslatorFrench; break;
 #endif
-#ifdef LANG_PL
-  else if (L_EQUAL("polish"))
-  {
-    theTranslator=new TranslatorPolish;
-  }
+#ifdef LANG_DE
+    case OUTPUT_LANGUAGE_t::German:              theTranslator = new TranslatorGerman; break;
 #endif
-#ifdef LANG_PT
-  else if (L_EQUAL("portuguese"))
-  {
-    theTranslator=new TranslatorPortuguese;
-  }
+#ifdef LANG_GR
+    case OUTPUT_LANGUAGE_t::Greek:               theTranslator = new TranslatorGreek; break;
 #endif
 #ifdef LANG_HU
-  else if (L_EQUAL("hungarian"))
-  {
-    theTranslator=new TranslatorHungarian;
-  }
+    case OUTPUT_LANGUAGE_t::Hungarian:           theTranslator = new TranslatorHungarian; break;
+#endif
+#ifdef LANG_ID
+    case OUTPUT_LANGUAGE_t::Indonesian:          theTranslator = new TranslatorIndonesian; break;
+#endif
+#ifdef LANG_IT
+    case OUTPUT_LANGUAGE_t::Italian:             theTranslator = new TranslatorItalian; break;
+#endif
+#ifdef LANG_JP
+    case OUTPUT_LANGUAGE_t::Japanese:            theTranslator = new TranslatorJapanese; break;
+#endif
+#ifdef LANG_JE
+    case OUTPUT_LANGUAGE_t::Japanese_en:         theTranslator = new TranslatorJapaneseEn; break;
 #endif
 #ifdef LANG_KR
-  else if (L_EQUAL("korean"))
-  {
-    theTranslator=new TranslatorKorean;
-  }
+    case OUTPUT_LANGUAGE_t::Korean:              theTranslator = new TranslatorKorean; break;
 #endif
 #ifdef LANG_KE
-  else if (L_EQUAL("korean-en"))
-  {
-    theTranslator=new TranslatorKoreanEn;
-  }
+    case OUTPUT_LANGUAGE_t::Korean_en:           theTranslator = new TranslatorKoreanEn; break;
 #endif
-#ifdef LANG_RO
-  else if (L_EQUAL("romanian"))
-  {
-    theTranslator=new TranslatorRomanian;
-  }
-#endif
-#ifdef LANG_SI
-  else if (L_EQUAL("slovene"))
-  {
-    theTranslator=new TranslatorSlovene;
-  }
+#ifdef LANG_LV
+    case OUTPUT_LANGUAGE_t::Latvian:             theTranslator = new TranslatorLatvian; break;
 #endif
-#ifdef LANG_CN
-  else if (L_EQUAL("chinese"))
-  {
-    theTranslator=new TranslatorChinese;
-  }
+#ifdef LANG_LT
+    case OUTPUT_LANGUAGE_t::Lithuanian:          theTranslator = new TranslatorLithuanian; break;
 #endif
-#ifdef LANG_TW
-  else if (L_EQUAL("chinese-traditional"))
-  {
-    theTranslator=new TranslatorChinesetraditional;
-  }
+#ifdef LANG_MK
+    case OUTPUT_LANGUAGE_t::Macedonian:          theTranslator = new TranslatorMacedonian; break;
 #endif
 #ifdef LANG_NO
-  else if (L_EQUAL("norwegian"))
-  {
-    theTranslator=new TranslatorNorwegian;
-  }
+    case OUTPUT_LANGUAGE_t::Norwegian:           theTranslator = new TranslatorNorwegian; break;
 #endif
-#ifdef LANG_BR
-  else if (L_EQUAL("brazilian"))
-  {
-    theTranslator=new TranslatorBrazilian;
-  }
+#ifdef LANG_FA
+    case OUTPUT_LANGUAGE_t::Persian:             theTranslator = new TranslatorPersian; break;
 #endif
-#ifdef LANG_DK
-  else if (L_EQUAL("danish"))
-  {
-    theTranslator=new TranslatorDanish;
-  }
+#ifdef LANG_PL
+    case OUTPUT_LANGUAGE_t::Polish:              theTranslator = new TranslatorPolish; break;
 #endif
-#ifdef LANG_SK
-  else if (L_EQUAL("slovak"))
-  {
-    theTranslator=new TranslatorSlovak;
-  }
+#ifdef LANG_PT
+    case OUTPUT_LANGUAGE_t::Portuguese:          theTranslator = new TranslatorPortuguese; break;
 #endif
-#ifdef LANG_UA
-  else if (L_EQUAL("ukrainian"))
-  {
-    theTranslator=new TranslatorUkrainian;
-  }
+#ifdef LANG_RO
+    case OUTPUT_LANGUAGE_t::Romanian:            theTranslator = new TranslatorRomanian; break;
 #endif
-#ifdef LANG_GR
-  else if (L_EQUAL("greek"))
-  {
-    theTranslator=new TranslatorGreek;
-  }
+#ifdef LANG_RU
+    case OUTPUT_LANGUAGE_t::Russian:             theTranslator = new TranslatorRussian; break;
 #endif
 #ifdef LANG_SR
-  else if (L_EQUAL("serbian"))
-  {
-    theTranslator=new TranslatorSerbian;
-  }
+    case OUTPUT_LANGUAGE_t::Serbian:             theTranslator = new TranslatorSerbian; break;
 #endif
 #ifdef LANG_SC
-  else if (L_EQUAL("serbian-cyrillic") || L_EQUAL("serbiancyr")) /* serbiancyr for consistency with older versions */
-  {
-    theTranslator=new TranslatorSerbianCyrillic;
-  }
-#endif
-#ifdef LANG_CA
-  else if (L_EQUAL("catalan"))
-  {
-    theTranslator=new TranslatorCatalan;
-  }
+    case OUTPUT_LANGUAGE_t::Serbian_Cyrillic:    theTranslator = new TranslatorSerbianCyrillic; break;
 #endif
-#ifdef LANG_LT
-  else if (L_EQUAL("lithuanian"))
-  {
-    theTranslator=new TranslatorLithuanian;
-  }
+#ifdef LANG_SK
+    case OUTPUT_LANGUAGE_t::Slovak:              theTranslator = new TranslatorSlovak; break;
 #endif
-#ifdef LANG_LV
-  else if (L_EQUAL("latvian"))
-  {
-    theTranslator=new TranslatorLatvian;
-  }
+#ifdef LANG_SI
+    case OUTPUT_LANGUAGE_t::Slovene:             theTranslator = new TranslatorSlovene; break;
 #endif
-#ifdef LANG_ZA
-  else if (L_EQUAL("afrikaans"))
-  {
-    theTranslator=new TranslatorAfrikaans;
-  }
+#ifdef LANG_ES
+    case OUTPUT_LANGUAGE_t::Spanish:             theTranslator = new TranslatorSpanish; break;
 #endif
-#ifdef LANG_AR
-  else if (L_EQUAL("arabic"))
-  {
-    theTranslator=new TranslatorArabic;
-  }
+#ifdef LANG_SV
+    case OUTPUT_LANGUAGE_t::Swedish:             theTranslator = new TranslatorSwedish; break;
 #endif
-#ifdef LANG_FA
-  else if (L_EQUAL("persian") || L_EQUAL("farsi"))
-  {
-    theTranslator=new TranslatorPersian;
-  }
+#ifdef LANG_TR
+    case OUTPUT_LANGUAGE_t::Turkish:             theTranslator = new TranslatorTurkish; break;
 #endif
-#ifdef LANG_MK
-  else if (L_EQUAL("macedonian"))
-  {
-    theTranslator=new TranslatorMacedonian;
-  }
+#ifdef LANG_UA
+    case OUTPUT_LANGUAGE_t::Ukrainian:           theTranslator = new TranslatorUkrainian; break;
 #endif
 #ifdef LANG_VI
-  else if (L_EQUAL("vietnamese"))
-  {
-    theTranslator=new TranslatorVietnamese;
-  }
-#endif
-#ifdef LANG_TR
-  else if (L_EQUAL("turkish"))
-  {
-    theTranslator=new TranslatorTurkish;
-  }
+    case OUTPUT_LANGUAGE_t::Vietnamese:          theTranslator = new TranslatorVietnamese; break;
 #endif
-#ifdef LANG_EO
-  else if (L_EQUAL("esperanto"))
-  {
-    theTranslator=new TranslatorEsperanto;
-  }
 #endif
-#endif // ENGLISH_ONLY
-  else // use the default language (i.e. english)
-  {
-    theTranslator=new TranslatorEnglish;
-    return FALSE;
   }
-
-  QCString msg = theTranslator->updateNeededMessage();
-  if (!msg.isEmpty()) warn_uncond("%s", qPrint(msg));
-  return TRUE;
 }
index 8f38bfc..ad74986 100644 (file)
@@ -19,8 +19,9 @@
 #define LANGUAGE_H
 
 #include "translator.h"
+#include "configvalues.h"
 
 extern Translator *theTranslator;
-extern bool setTranslator(const QCString &languageName);
+extern void setTranslator(OUTPUT_LANGUAGE_t languageName);
 
 #endif
index 7a551d3..3c5a435 100644 (file)
@@ -38,6 +38,7 @@
 #include "emoji.h"
 #include "plantuml.h"
 #include "fileinfo.h"
+#include "regex.h"
 
 const int maxLevels=5;
 static const char *secLabels[maxLevels] =
@@ -52,6 +53,26 @@ static const char *getSectionName(int level)
   return secLabels[std::min(maxLevels-1,l)];
 }
 
+static void insertDimension(TextStream &t, QCString dimension, const char *orientationString)
+{
+  // dimensions for latex images can be a percentage, in this case they need some extra
+  // handling as the % symbol is used for comments
+  static const reg::Ex re(R"((\d+)%)");
+  std::string s = dimension.str();
+  reg::Match match;
+  if (reg::search(s,match,re))
+  {
+    bool ok;
+    double percent = QCString(match[1].str()).toInt(&ok);
+    if (ok)
+    {
+      t << percent/100.0 << "\\text" << orientationString;
+      return;
+    }
+  }
+  t << dimension;
+}
+
 static void visitPreStart(TextStream &t, bool hasCaption, QCString name,  QCString width,  QCString height, bool inlineImage = FALSE)
 {
     if (inlineImage)
@@ -78,7 +99,8 @@ static void visitPreStart(TextStream &t, bool hasCaption, QCString name,  QCStri
     }
     if (!width.isEmpty())
     {
-      t << "width=" << width;
+      t << "width=";
+      insertDimension(t, width, "width");
     }
     if (!width.isEmpty() && !height.isEmpty())
     {
@@ -86,7 +108,8 @@ static void visitPreStart(TextStream &t, bool hasCaption, QCString name,  QCStri
     }
     if (!height.isEmpty())
     {
-      t << "height=" << height;
+      t << "height=";
+      insertDimension(t, height, "height");
     }
     if (width.isEmpty() && height.isEmpty())
     {
@@ -179,8 +202,8 @@ QCString LatexDocVisitor::escapeMakeIndexChars(const char *s)
 LatexDocVisitor::LatexDocVisitor(TextStream &t,LatexCodeGenerator &ci,
                                  const QCString &langExt,bool insideTabbing)
   : DocVisitor(DocVisitor_Latex), m_t(t), m_ci(ci), m_insidePre(FALSE),
-    m_insideItem(FALSE), m_hide(FALSE), m_hideCaption(FALSE), m_insideTabbing(insideTabbing),
-    m_langExt(langExt)
+    m_insideItem(FALSE), m_hide(FALSE), m_hideCaption(FALSE),
+    m_insideTabbing(insideTabbing), m_langExt(langExt)
 {
 }
 
@@ -218,16 +241,31 @@ void LatexDocVisitor::visit(DocWhiteSpace *w)
 void LatexDocVisitor::visit(DocSymbol *s)
 {
   if (m_hide) return;
+  bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
   const char *res = HtmlEntityMapper::instance()->latex(s->symbol());
   if (res)
   {
     if (((s->symbol() == DocSymbol::Sym_lt) || (s->symbol() == DocSymbol::Sym_Less))&& (!m_insidePre))
     {
-      m_t << "\\texorpdfstring{$<$}{<}";
+      if (pdfHyperlinks)
+      {
+        m_t << "\\texorpdfstring{$<$}{<}";
+      }
+      else
+      {
+        m_t << "$<$";
+      }
     }
     else if (((s->symbol() == DocSymbol::Sym_gt) || (s->symbol() == DocSymbol::Sym_Greater)) && (!m_insidePre))
     {
-      m_t << "\\texorpdfstring{$>$}{>}";
+      if (pdfHyperlinks)
+      {
+        m_t << "\\texorpdfstring{$>$}{>}";
+      }
+      else
+      {
+        m_t << "$>$";
+      }
     }
     else
     {
@@ -321,6 +359,9 @@ void LatexDocVisitor::visit(DocStyleChange *s)
     case DocStyleChange::Small:
       if (s->enable()) m_t << "\n\\footnotesize ";  else m_t << "\n\\normalsize ";
       break;
+    case DocStyleChange::Cite:
+      if (s->enable()) m_t << "{\\itshape ";     else m_t << "}";
+      break;
     case DocStyleChange::Preformatted:
       if (s->enable())
       {
@@ -335,6 +376,12 @@ void LatexDocVisitor::visit(DocStyleChange *s)
       break;
     case DocStyleChange::Div:  /* HTML only */ break;
     case DocStyleChange::Span: /* HTML only */ break;
+    case DocStyleChange::Details: /* emulation of the <details> tag */
+      if (!s->enable()) m_t << "\n\n";
+      break;
+    case DocStyleChange::Summary: /* emulation of the <summary> tag inside a <details> tag */
+      if (s->enable()) m_t << "{\\bfseries{";      else m_t << "}}";
+      break;
   }
 }
 
@@ -357,6 +404,14 @@ void LatexDocVisitor::visit(DocVerbatim *s)
         m_ci.endCodeFragment("DoxyCode");
       }
       break;
+    case DocVerbatim::JavaDocLiteral:
+      filter(s->text(), true);
+      break;
+    case DocVerbatim::JavaDocCode:
+      m_t << "{\\ttfamily ";
+      filter(s->text(), true);
+      m_t << "}";
+      break;
     case DocVerbatim::Verbatim:
       m_t << "\\begin{DoxyVerb}";
       m_t << s->text();
@@ -665,12 +720,15 @@ void LatexDocVisitor::visit(DocCite *cite)
 void LatexDocVisitor::visitPre(DocAutoList *l)
 {
   if (m_hide) return;
+  if (m_indentLevel>=maxIndentLevels-1) return;
   if (l->isEnumList())
   {
     m_t << "\n\\begin{DoxyEnumerate}";
+    m_listItemInfo[indentLevel()].isEnum = true;
   }
   else
   {
+    m_listItemInfo[indentLevel()].isEnum = false;
     m_t << "\n\\begin{DoxyItemize}";
   }
 }
@@ -678,6 +736,7 @@ void LatexDocVisitor::visitPre(DocAutoList *l)
 void LatexDocVisitor::visitPost(DocAutoList *l)
 {
   if (m_hide) return;
+  if (m_indentLevel>=maxIndentLevels-1) return;
   if (l->isEnumList())
   {
     m_t << "\n\\end{DoxyEnumerate}";
@@ -692,10 +751,12 @@ void LatexDocVisitor::visitPre(DocAutoListItem *)
 {
   if (m_hide) return;
   m_t << "\n\\item ";
+  incIndentLevel();
 }
 
 void LatexDocVisitor::visitPost(DocAutoListItem *)
 {
+  decIndentLevel();
 }
 
 void LatexDocVisitor::visitPre(DocPara *)
@@ -712,12 +773,14 @@ void LatexDocVisitor::visitPost(DocPara *p)
      ) m_t << "\n\n";
 }
 
-void LatexDocVisitor::visitPre(DocRoot *)
+void LatexDocVisitor::visitPre(DocRoot *r)
 {
+  //if (r->indent()) incIndentLevel();
 }
 
-void LatexDocVisitor::visitPost(DocRoot *)
+void LatexDocVisitor::visitPost(DocRoot *r)
 {
+  //if (r->indent()) decIndentLevel();
 }
 
 void LatexDocVisitor::visitPre(DocSimpleSect *s)
@@ -797,6 +860,7 @@ void LatexDocVisitor::visitPre(DocSimpleSect *s)
   // special case 1: user defined title
   if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
   {
+    incIndentLevel();
     m_t << "}\n";
   }
   else
@@ -864,6 +928,7 @@ void LatexDocVisitor::visitPost(DocSimpleSect *s)
     default:
       break;
   }
+  decIndentLevel();
 }
 
 void LatexDocVisitor::visitPre(DocTitle *)
@@ -881,6 +946,7 @@ void LatexDocVisitor::visitPre(DocSimpleList *)
 {
   if (m_hide) return;
   m_t << "\\begin{DoxyItemize}\n";
+  m_listItemInfo[indentLevel()].isEnum = false;
 }
 
 void LatexDocVisitor::visitPost(DocSimpleList *)
@@ -893,10 +959,12 @@ void LatexDocVisitor::visitPre(DocSimpleListItem *)
 {
   if (m_hide) return;
   m_t << "\\item ";
+  incIndentLevel();
 }
 
 void LatexDocVisitor::visitPost(DocSimpleListItem *)
 {
+  decIndentLevel();
 }
 
 void LatexDocVisitor::visitPre(DocSection *s)
@@ -918,6 +986,8 @@ void LatexDocVisitor::visitPost(DocSection *)
 void LatexDocVisitor::visitPre(DocHtmlList *s)
 {
   if (m_hide) return;
+  if (m_indentLevel>=maxIndentLevels-1) return;
+  m_listItemInfo[indentLevel()].isEnum = s->type()==DocHtmlList::Ordered;
   if (s->type()==DocHtmlList::Ordered)
   {
     bool first = true;
@@ -960,7 +1030,9 @@ void LatexDocVisitor::visitPre(DocHtmlList *s)
       else if (opt.name=="start")
       {
         m_t << (first ?  "[": ",");
-        m_t << "start=" << opt.value;
+        bool ok;
+        int val = opt.value.toInt(&ok);
+        if (ok) m_t << "start=" << val;
         first = false;
       }
     }
@@ -973,20 +1045,38 @@ void LatexDocVisitor::visitPre(DocHtmlList *s)
 void LatexDocVisitor::visitPost(DocHtmlList *s)
 {
   if (m_hide) return;
+  if (m_indentLevel>=maxIndentLevels-1) return;
   if (s->type()==DocHtmlList::Ordered)
     m_t << "\n\\end{DoxyEnumerate}";
   else
     m_t << "\n\\end{DoxyItemize}";
 }
 
-void LatexDocVisitor::visitPre(DocHtmlListItem *)
+void LatexDocVisitor::visitPre(DocHtmlListItem *l)
 {
   if (m_hide) return;
+  if (m_listItemInfo[indentLevel()].isEnum)
+  {
+    for (const auto &opt : l->attribs())
+    {
+      if (opt.name=="value")
+      {
+        bool ok;
+        int val = opt.value.toInt(&ok);
+        if (ok)
+        {
+          m_t << "\n\\setcounter{DoxyEnumerate" << integerToRoman(indentLevel()+1,false) << "}{" << (val - 1) << "}";
+        }
+      }
+    }
+  }
   m_t << "\n\\item ";
+  incIndentLevel();
 }
 
 void LatexDocVisitor::visitPost(DocHtmlListItem *)
 {
+  decIndentLevel();
 }
 
 //void LatexDocVisitor::visitPre(DocHtmlPre *)
@@ -1077,10 +1167,12 @@ void LatexDocVisitor::visitPost(DocHtmlDescTitle *)
 
 void LatexDocVisitor::visitPre(DocHtmlDescData *)
 {
+  incIndentLevel();
 }
 
 void LatexDocVisitor::visitPost(DocHtmlDescData *)
 {
+  decIndentLevel();
 }
 
 static bool tableIsNested(const DocNode *n)
@@ -1464,6 +1556,7 @@ void LatexDocVisitor::visitPost(DocImage *img)
 void LatexDocVisitor::visitPre(DocDotFile *df)
 {
   if (m_hide) return;
+  if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(LATEX_OUTPUT)+"/"+stripPath(df->file()));
   startDotFile(df->file(),df->width(),df->height(),df->hasCaption(),df->srcFile(),df->srcLine());
 }
 
@@ -1475,6 +1568,7 @@ void LatexDocVisitor::visitPost(DocDotFile *df)
 void LatexDocVisitor::visitPre(DocMscFile *df)
 {
   if (m_hide) return;
+  if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(LATEX_OUTPUT)+"/"+stripPath(df->file()));
   startMscFile(df->file(),df->width(),df->height(),df->hasCaption(),df->srcFile(),df->srcLine());
 }
 
@@ -1487,6 +1581,7 @@ void LatexDocVisitor::visitPost(DocMscFile *df)
 void LatexDocVisitor::visitPre(DocDiaFile *df)
 {
   if (m_hide) return;
+  if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(LATEX_OUTPUT)+"/"+stripPath(df->file()));
   startDiaFile(df->file(),df->width(),df->height(),df->hasCaption(),df->srcFile(),df->srcLine());
 }
 
@@ -1577,11 +1672,13 @@ void LatexDocVisitor::visitPre(DocSecRefList *)
   m_t << "\\footnotesize\n";
   m_t << "\\begin{multicols}{2}\n";
   m_t << "\\begin{DoxyCompactList}\n";
+  incIndentLevel();
 }
 
 void LatexDocVisitor::visitPost(DocSecRefList *)
 {
   if (m_hide) return;
+  decIndentLevel();
   m_t << "\\end{DoxyCompactList}\n";
   m_t << "\\end{multicols}\n";
   m_t << "\\normalsize\n";
@@ -1616,6 +1713,7 @@ void LatexDocVisitor::visitPre(DocParamSect *s)
       break;
     default:
       ASSERT(0);
+      incIndentLevel();
   }
   m_t << "}\n";
 }
@@ -1640,6 +1738,7 @@ void LatexDocVisitor::visitPost(DocParamSect *s)
       break;
     default:
       ASSERT(0);
+      decIndentLevel();
   }
 }
 
@@ -1752,6 +1851,7 @@ void LatexDocVisitor::visitPre(DocXRefItem *x)
   static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
   if (m_hide) return;
   if (x->title().isEmpty()) return;
+  incIndentLevel();
   m_t << "\\begin{DoxyRefDesc}{";
   filter(x->title());
   m_t << "}\n";
@@ -1779,6 +1879,7 @@ void LatexDocVisitor::visitPost(DocXRefItem *x)
 {
   if (m_hide) return;
   if (x->title().isEmpty()) return;
+  decIndentLevel();
   m_t << "\\end{DoxyRefDesc}\n";
 }
 
@@ -1806,12 +1907,14 @@ void LatexDocVisitor::visitPre(DocHtmlBlockQuote *)
 {
   if (m_hide) return;
   m_t << "\\begin{quote}\n";
+  incIndentLevel();
 }
 
 void LatexDocVisitor::visitPost(DocHtmlBlockQuote *)
 {
   if (m_hide) return;
   m_t << "\\end{quote}\n";
+  decIndentLevel();
 }
 
 void LatexDocVisitor::visitPre(DocVhdlFlow *)
@@ -1834,14 +1937,15 @@ void LatexDocVisitor::visitPost(DocParBlock *)
   if (m_hide) return;
 }
 
-void LatexDocVisitor::filter(const QCString &str)
+void LatexDocVisitor::filter(const QCString &str, const bool retainNewLine)
 {
   filterLatexString(m_t,str,
                     m_insideTabbing,
                     m_insidePre,
                     m_insideItem,
                     m_ci.usedTableLevel()>0,  // insideTable
-                    false                     // keepSpaces
+                    false, // keepSpaces
+                    retainNewLine
                    );
 }
 
@@ -2044,3 +2148,25 @@ void LatexDocVisitor::writePlantUMLFile(const QCString &baseName, DocVerbatim *s
   visitPostEnd(m_t, s->hasCaption());
 }
 
+int LatexDocVisitor::indentLevel() const
+{
+  return std::min(m_indentLevel,maxIndentLevels-1);
+}
+
+void LatexDocVisitor::incIndentLevel()
+{
+  m_indentLevel++;
+  if (m_indentLevel>=maxIndentLevels)
+  {
+    err("Maximum indent level (%d) exceeded while generating LaTeX output!\n",maxIndentLevels-1);
+  }
+}
+
+void LatexDocVisitor::decIndentLevel()
+{
+  if (m_indentLevel>0)
+  {
+    m_indentLevel--;
+  }
+}
+
index 745c7a8..470aaf4 100644 (file)
@@ -24,6 +24,7 @@
 class LatexCodeGenerator;
 class TextStream;
 
+
 /*! @brief Concrete visitor implementation for LaTeX output. */
 class LatexDocVisitor : public DocVisitor
 {
@@ -152,7 +153,7 @@ class LatexDocVisitor : public DocVisitor
     // helper functions
     //--------------------------------------
 
-    void filter(const QCString &str);
+    void filter(const QCString &str, const bool retainNewLine = false);
     void startLink(const QCString &ref,const QCString &file,
                    const QCString &anchor,bool refToTable=FALSE);
     void endLink(const QCString &ref,const QCString &file,
@@ -176,6 +177,10 @@ class LatexDocVisitor : public DocVisitor
     void writeDiaFile(const QCString &fileName, DocVerbatim *s);
     void writePlantUMLFile(const QCString &fileName, DocVerbatim *s);
 
+    void incIndentLevel();
+    void decIndentLevel();
+    int indentLevel() const;
+
     //--------------------------------------
     // state variables
     //--------------------------------------
@@ -201,6 +206,16 @@ class LatexDocVisitor : public DocVisitor
     std::stack<TableState> m_tableStateStack; // needed for nested tables
     RowSpanList m_emptyRowSpanList;
 
+    static const int maxIndentLevels = 13;
+    int m_indentLevel = 0;
+
+    struct LatexListItemInfo
+    {
+      bool isEnum = false;
+    };
+
+    LatexListItemInfo m_listItemInfo[maxIndentLevels];
+
     void pushTableState()
     {
       m_tableStateStack.push(TableState());
@@ -263,5 +278,4 @@ class LatexDocVisitor : public DocVisitor
     }
 
 };
-
 #endif
index 60cd26e..bc01e01 100644 (file)
@@ -1,8 +1,6 @@
 /******************************************************************************
  *
- *
- *
- * Copyright (C) 1997-2015 by Dimitri van Heesch.
+ * Copyright (C) 1997-2021 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
@@ -171,7 +169,7 @@ void LatexCodeGenerator::writeCodeLink(CodeSymbolType,
   m_col+=l;
 }
 
-void LatexCodeGenerator::writeLineNumber(const QCString &ref,const QCString &fileName,const QCString &anchor,int l)
+void LatexCodeGenerator::writeLineNumber(const QCString &ref,const QCString &fileName,const QCString &anchor,int l,bool writeLineAnchor)
 {
   bool usePDFLatex = Config_getBool(USE_PDFLATEX);
   bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
@@ -191,7 +189,7 @@ void LatexCodeGenerator::writeLineNumber(const QCString &ref,const QCString &fil
       lineAnchor.sprintf("_l%05d",l);
       lineAnchor.prepend(stripExtensionGeneral(m_sourceFileName, ".tex"));
     }
-    bool showTarget = usePDFLatex && pdfHyperlinks && !lineAnchor.isEmpty();
+    bool showTarget = usePDFLatex && pdfHyperlinks && !lineAnchor.isEmpty() && writeLineAnchor;
     if (showTarget)
     {
       m_t << "\\Hypertarget{" << stripPath(lineAnchor) << "}";
@@ -295,8 +293,8 @@ static void writeLatexMakefile()
   }
   TextStream t(&f);
   // inserted by KONNO Akihisa <konno@researchers.jp> 2002-03-05
-  QCString latex_command = theTranslator->latexCommandName();
-  QCString mkidx_command = Config_getString(MAKEINDEX_CMD_NAME);
+  QCString latex_command = theTranslator->latexCommandName().quoted();
+  QCString mkidx_command = Config_getString(MAKEINDEX_CMD_NAME).quoted();
   // end insertion by KONNO Akihisa <konno@researchers.jp> 2002-03-05
   if (!Config_getBool(USE_PDFLATEX)) // use plain old latex
   {
@@ -383,8 +381,8 @@ static void writeMakeBat()
 #if defined(_MSC_VER)
   QCString dir=Config_getString(LATEX_OUTPUT);
   QCString fileName=dir+"/make.bat";
-  QCString latex_command = theTranslator->latexCommandName();
-  QCString mkidx_command = Config_getString(MAKEINDEX_CMD_NAME);
+  QCString latex_command = theTranslator->latexCommandName().quoted();
+  QCString mkidx_command = Config_getString(MAKEINDEX_CMD_NAME).quoted();
   bool generateBib = !CitationManager::instance().isEmpty();
   std::ofstream t(fileName.str(),std::ofstream::out | std::ofstream::binary);
   if (!t.is_open())
@@ -608,7 +606,7 @@ static QCString substituteLatexKeywords(const QCString &str,
   bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
   bool usePdfLatex = Config_getBool(USE_PDFLATEX);
   bool latexBatchmode = Config_getBool(LATEX_BATCHMODE);
-  QCString paperType = Config_getString(PAPER_TYPE);
+  QCString paperType = Config_getEnumAsString(PAPER_TYPE);
 
   QCString style = Config_getString(LATEX_BIB_STYLE);
   if (style.isEmpty())
index 727c4be..8c76098 100644 (file)
@@ -44,7 +44,7 @@ class LatexCodeGenerator : public CodeOutputInterface
                       const SourceLinkInfo &,
                       const SourceLinkInfo &
                      )  override{}
-    void writeLineNumber(const QCString &,const QCString &,const QCString &,int) override;
+    void writeLineNumber(const QCString &,const QCString &,const QCString &,int,bool) override;
     void startCodeLine(bool) override;
     void endCodeLine() override;
     void startFontClass(const QCString &) override;
@@ -101,8 +101,8 @@ class LatexGenerator : public OutputGenerator
                        const QCString &anchor,const QCString &name,
                        const QCString &tooltip)
     { m_codeGen.writeCodeLink(type,ref,file,anchor,name,tooltip); }
-    void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor,int lineNumber)
-    { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber); }
+    void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor,int lineNumber, bool writeLineAnchor)
+    { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber,writeLineAnchor); }
     void writeTooltip(const QCString &id, const DocLinkInfo &docInfo, const QCString &decl,
                       const QCString &desc, const SourceLinkInfo &defInfo, const SourceLinkInfo &declInfo
                      )
index 7c368be..f2a8e9d 100644 (file)
@@ -89,6 +89,10 @@ static bool elemIsVisible(const XMLHandlers::Attributes &attrib,bool defVal=TRUE
     {
       return ConfigValues::instance().*(opt->value.b);
     }
+    else if (opt && opt->type==ConfigValues::Info::String)
+    {
+      return ConfigValues::instance().*(opt->value.s) != "NO";
+    }
     else if (!opt)
     {
       err("found unsupported value %s for visible attribute in layout file\n",
@@ -98,6 +102,11 @@ static bool elemIsVisible(const XMLHandlers::Attributes &attrib,bool defVal=TRUE
   return visible!="no" && visible!="0";
 }
 
+static bool parentIsVisible(LayoutNavEntry *parent)
+{
+  return parent==0 || parent->visible();
+}
+
 //---------------------------------------------------------------------------------
 
 LayoutNavEntry *LayoutNavEntry::find(LayoutNavEntry::Kind kind,
@@ -118,15 +127,13 @@ LayoutNavEntry *LayoutNavEntry::find(LayoutNavEntry::Kind kind,
   return result;
 }
 
-
-
 QCString LayoutNavEntry::url() const
 {
   QCString url = baseFile().stripWhiteSpace();
   if ((kind()!=LayoutNavEntry::User && kind()!=LayoutNavEntry::UserGroup) ||
       (kind()==LayoutNavEntry::UserGroup && url.left(9)=="usergroup"))
   {
-    url+=Doxygen::htmlFileExtension;
+    url = addHtmlExtensionIfMissing(url);
   }
   else if (url.left(5)=="@ref " || url.left(5)=="\\ref ")
   {
@@ -137,7 +144,7 @@ QCString LayoutNavEntry::url() const
     {
       if (d && d->isLinkable())
       {
-        url=d->getOutputFileBase()+Doxygen::htmlFileExtension;
+        url=addHtmlExtensionIfMissing(d->getOutputFileBase());
         if (!anchor.isEmpty())
         {
           url+="#"+anchor;
@@ -179,7 +186,7 @@ class LayoutParser
 
     void startSimpleEntry(LayoutDocEntry::Kind k,const XMLHandlers::Attributes &attrib)
     {
-      bool isVisible = elemIsVisible(attrib);
+      bool isVisible = elemIsVisible(attrib) && parentIsVisible(m_rootNav);
       if (m_part!=-1 && isVisible)
       {
         LayoutDocManager::instance().addEntry((LayoutDocManager::LayoutPart)m_part,
@@ -192,7 +199,7 @@ class LayoutParser
     void startSectionEntry(LayoutDocEntry::Kind k,const XMLHandlers::Attributes &attrib,
                            const QCString &title)
     {
-      bool isVisible = elemIsVisible(attrib);
+      bool isVisible = elemIsVisible(attrib) && parentIsVisible(m_rootNav);
       QCString userTitle = XMLHandlers::value(attrib,"title");
       //printf("startSectionEntry: title='%s' userTitle='%s'\n",
       //    qPrint(title),qPrint(userTitle));
@@ -243,7 +250,10 @@ class LayoutParser
     {
       m_scope="navindex/";
       m_rootNav = LayoutDocManager::instance().rootNavEntry();
-      if (m_rootNav) m_rootNav->clear();
+      if (m_rootNav)
+      {
+        m_rootNav->clear();
+      }
     }
 
     void endNavIndex()
@@ -524,7 +534,7 @@ class LayoutParser
       }
       QCString baseFile = mapping[i].baseFile;
       QCString title = XMLHandlers::value(attrib,"title");
-      bool isVisible = elemIsVisible(attrib);
+      bool isVisible = elemIsVisible(attrib) && parentIsVisible(m_rootNav);
       if (title.isEmpty()) // use default title
       {
         title = mapping[i].mainName; // use title for main row
@@ -548,7 +558,14 @@ class LayoutParser
       {
         if (!url.isEmpty())
         {
-          baseFile=url;
+          if (url == "[none]")
+          {
+            baseFile = QCString();
+          }
+          else
+          {
+            baseFile=url;
+          }
         }
         else
         {
@@ -707,6 +724,8 @@ class LayoutParser
 
 //---------------------------------------------------------------------------------
 
+namespace {
+
 struct ElementCallbacks
 {
   using StartCallback = std::function<void(LayoutParser&,const XMLHandlers::Attributes&)>;
@@ -1495,6 +1514,9 @@ static const std::map< std::string, ElementCallbacks > g_elementHandlers =
 
 };
 
+
+} // namespace
+
 void LayoutParser::startElement( const std::string &name, const XMLHandlers::Attributes& attrib )
 {
   //printf("startElement [%s]::[%s]\n",qPrint(m_scope),qPrint(name));
index 04fdf52..9b76287 100644 (file)
@@ -180,7 +180,7 @@ struct LayoutNavEntry
     LayoutNavEntry *find(LayoutNavEntry::Kind k,const QCString &file=QCString()) const;
 
   private:
-    LayoutNavEntry() : m_parent(0), m_kind(None), m_visible(FALSE) {}
+    LayoutNavEntry() : m_parent(0), m_kind(None), m_visible(true) {}
     LayoutNavEntry *m_parent;
     Kind m_kind;
     bool m_visible;
index a2c0a97..9ac4c45 100644 (file)
 %option extra-type="struct lexcodeYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -47,8 +51,9 @@ struct lexcodeYY_state
      const char   *inputString;     //!< the code fragment as text
      yy_size_t     inputPosition;   //!< read offset during parsing
      int           inputLines;      //!< number of line in the code fragment
+     QCString      fileName;
      int           yyLineNr;        //!< current line number
-     bool          needsTermination;
+     bool          insideCodeLine = false;
 
      bool          lineNumbers = FALSE;
      const Definition   *searchCtx;
@@ -102,6 +107,10 @@ static void handleCCode(yyscan_t yyscanner);
 #undef YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
+
 %}
 
 nl              (\r\n|\r|\n)
@@ -628,11 +637,11 @@ NONLopt [^\n]*
                           }
 <Comment>{CCS}             { yyextra->CCodeBuffer += yytext ; }
 <Comment>{CPPC}             { yyextra->CCodeBuffer += yytext ; }
-<Comment>{CMD}("code"|"verbatim")       {
+<Comment>{CMD}("code"|"verbatim"|"iliteral")       {
                             yyextra->insideCode=TRUE;
                             yyextra->CCodeBuffer += yytext ;
                           }
-<Comment>{CMD}("endcode"|"endverbatim") {
+<Comment>{CMD}("endcode"|"endverbatim"|"endiliteral") {
                             yyextra->insideCode=FALSE;
                             yyextra->CCodeBuffer += yytext ;
                           }
@@ -757,7 +766,7 @@ NONLopt [^\n]*
                             yyextra->nestedComment=FALSE;
                             BEGIN(DocCopyBlock);
                           }
-<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!)
+<DocBlock>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!)
                             yyextra->CCodeBuffer += yytext;
                             yyextra->docBlockName=&yytext[1];
                             yyextra->fencedSize=0;
@@ -816,7 +825,7 @@ NONLopt [^\n]*
                               BEGIN(DocBlock);
                             }
                           }
-<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block
+<DocCopyBlock>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block
                             yyextra->CCodeBuffer += yytext;
                             if (&yytext[4]==yyextra->docBlockName)
                             {
@@ -825,11 +834,7 @@ NONLopt [^\n]*
                           }
 <DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line
                             yyextra->CCodeBuffer += yytext;
-                            if (yyextra->docBlockName=="verbatim")
-                            {
-                              REJECT;
-                            }
-                            else if (yyextra->docBlockName=="code")
+                            if ((yyextra->docBlockName=="verbatim") || (yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral"))
                             {
                               REJECT;
                             }
@@ -839,7 +844,7 @@ NONLopt [^\n]*
                             }
                           }
 <DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s
-                            if (yyextra->docBlockName=="code")
+                            if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral"))
                             {
                               yyextra->CCodeBuffer += yytext;
                             }
@@ -849,7 +854,7 @@ NONLopt [^\n]*
                             }
                           }
 <DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516)
-                            if (yyextra->docBlockName=="code")
+                            if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral"))
                             {
                               yyextra->CCodeBuffer += yytext;
                             }
@@ -859,7 +864,7 @@ NONLopt [^\n]*
                             }
                           }
 <DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one *
-                            if (yyextra->docBlockName=="code")
+                            if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral"))
                             {
                               if (yyextra->nestedComment) // keep * it is part of the code
                               {
@@ -981,24 +986,28 @@ static void startCodeLine(yyscan_t yyscanner)
       {
         yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
                             yyextra->currentMemberDef->getOutputFileBase(),
-                            yyextra->currentMemberDef->anchor(),yyextra->yyLineNr);
+                            yyextra->currentMemberDef->anchor(),yyextra->yyLineNr,
+                            !yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
       else
       {
         yyextra->code->writeLineNumber(d->getReference(),
                             d->getOutputFileBase(),
-                            QCString(),yyextra->yyLineNr);
+                            QCString(),yyextra->yyLineNr,
+                            !yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
     }
     else
     {
-      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr);
+      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr,
+                                     !yyextra->includeCodeFragment);
     }
   }
 
   yyextra->code->startCodeLine(yyextra->sourceFileDef && yyextra->lineNumbers);
+  yyextra->insideCodeLine = true;
 
   if (yyextra->currentFontClass)
   {
@@ -1021,13 +1030,17 @@ static void endCodeLine(yyscan_t yyscanner)
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   endFontClass(yyscanner);
   yyextra->code->endCodeLine();
+  yyextra->insideCodeLine = false;
 }
 
 static void nextCodeLine(yyscan_t yyscanner)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   const char *fc = yyextra->currentFontClass;
-  endCodeLine(yyscanner);
+  if (yyextra->insideCodeLine)
+  {
+    endCodeLine(yyscanner);
+  }
   if (yyextra->yyLineNr<yyextra->inputLines)
   {
     yyextra->currentFontClass = fc;
@@ -1054,15 +1067,7 @@ static void codifyLines(yyscan_t yyscanner,const QCString &text)
       memcpy(tmp,sp,l);
       tmp[l]='\0';
       yyextra->code->codify(tmp);
-      if (p)
-      {
-        nextCodeLine(yyscanner);
-      }
-      else
-      {
-        endCodeLine(yyscanner);
-        done=true;
-      }
+      nextCodeLine(yyscanner);
       free(tmp);
     }
     else
@@ -1100,9 +1105,7 @@ static int countLines(yyscan_t yyscanner)
   }
   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++,
-    yyextra->needsTermination=true;
+    count++;
   }
   return count;
 }
@@ -1140,7 +1143,7 @@ static void handleCCode(yyscan_t yyscanner)
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   if (yyextra->CCodeBuffer.isEmpty()) return;
 
-  yyextra->ccodeParser.setStartCodeLine(false);
+  yyextra->ccodeParser.setInsideCodeLine(yyextra->insideCodeLine);
   yyextra->ccodeParser.parseCode(*yyextra->code,
                yyextra->classScope,
                yyextra->CCodeBuffer,
@@ -1157,10 +1160,9 @@ static void handleCCode(yyscan_t yyscanner)
                yyextra->collectXRefs
               );
   yyextra->CCodeBuffer.resize(0);
-  yyextra->ccodeParser.setStartCodeLine(true);
+  yyextra->insideCodeLine = yyextra->ccodeParser.insideCodeLine();
   yyextra->yyLineNr--;
   codifyLines(yyscanner,"\n");
-  return;
 }
 
 // public interface -----------------------------------------------------------
@@ -1218,8 +1220,9 @@ void LexCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
   yyextra->code = &codeOutIntf;
   yyextra->inputString   = input.data();
   yyextra->inputPosition = 0;
+  yyextra->fileName      = fileDef ? fileDef->fileName():"";
   yyextra->currentFontClass = 0;
-  yyextra->needsTermination = false;
+  yyextra->insideCodeLine = false;
 
   yyextra->classScope=scopeName;
   yyextra->currentMemberDef=memberDef;
@@ -1264,7 +1267,7 @@ void LexCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
   BEGIN( DefSection );
   lexcodeYYlex(yyscanner);
 
-  if (yyextra->needsTermination)
+  if (yyextra->insideCodeLine)
   {
     endCodeLine(yyscanner);
   }
index 0c5ca31..a314d9d 100644 (file)
 
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -78,7 +82,7 @@ struct lexscannerYY_state
   QCString         cCodeBuffer;
   int              roundCount = 0;
 
-  QCString         yyFileName;
+  QCString         fileName;
   ClangTUParser   *clangParser = 0;
 
   std::shared_ptr<Entry> current;
@@ -99,6 +103,10 @@ static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
 #undef  YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
+
 %}
 
 nl              (\r\n|\r|\n)
@@ -614,11 +622,11 @@ NONLopt [^\n]*
                           }
 <Comment>{CCS}             { yyextra->cCodeBuffer += yytext ; }
 <Comment>{CPPC}             { yyextra->cCodeBuffer += yytext ; }
-<Comment>{CMD}("code"|"verbatim") {
+<Comment>{CMD}("code"|"verbatim"|"iliteral") {
                             yyextra->insideCode=TRUE;
                             yyextra->cCodeBuffer += yytext ;
                           }
-<Comment>{CMD}("endcode"|"endverbatim") {
+<Comment>{CMD}("endcode"|"endverbatim"|"endiliteral") {
                             yyextra->insideCode=FALSE;
                             yyextra->cCodeBuffer += yytext ;
                           }
@@ -739,7 +747,7 @@ NONLopt [^\n]*
                             yyextra->nestedComment=FALSE;
                             BEGIN(DocCopyBlock);
                           }
-<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!)
+<DocBlock>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!)
                             yyextra->cCodeBuffer += yytext;
                             yyextra->docBlockName=&yytext[1];
                             yyextra->fencedSize=0;
@@ -797,7 +805,7 @@ NONLopt [^\n]*
                               BEGIN(DocBlock);
                             }
                           }
-<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block
+<DocCopyBlock>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block
                             yyextra->cCodeBuffer += yytext;
                             if (yyextra->docBlockName==&yytext[4])
                             {
@@ -806,11 +814,7 @@ NONLopt [^\n]*
                           }
 <DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line
                             yyextra->cCodeBuffer += yytext;
-                            if (yyextra->docBlockName=="verbatim")
-                            {
-                              REJECT;
-                            }
-                            else if (yyextra->docBlockName=="code")
+                            if ((yyextra->docBlockName=="verbatim") || (yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral"))
                             {
                               REJECT;
                             }
@@ -820,7 +824,7 @@ NONLopt [^\n]*
                             }
                           }
 <DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s
-                            if (yyextra->docBlockName=="code")
+                            if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral"))
                             {
                               yyextra->cCodeBuffer += yytext;
                             }
@@ -830,7 +834,7 @@ NONLopt [^\n]*
                             }
                           }
 <DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516)
-                            if (yyextra->docBlockName=="code")
+                            if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral"))
                             {
                               yyextra->cCodeBuffer += yytext;
                             }
@@ -840,7 +844,7 @@ NONLopt [^\n]*
                             }
                           }
 <DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one *
-                            if (yyextra->docBlockName=="code")
+                            if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral"))
                             {
                               if (yyextra->nestedComment) // keep * it is part of the code
                               {
@@ -953,18 +957,18 @@ static void parseMain(yyscan_t yyscanner,
   lexscannerYYrestart(0,yyscanner);
 
   yyextra->current_root  = rt;
-  yyextra->yyFileName = fileName;
+  yyextra->fileName = fileName;
   yyextra->clangParser = clangParser;
-  yyextra->language    = getLanguageFromFileName(yyextra->yyFileName);
+  yyextra->language    = getLanguageFromFileName(yyextra->fileName);
   rt->lang = yyextra->language;
-  msg("Parsing file %s...\n",qPrint(yyextra->yyFileName));
+  msg("Parsing file %s...\n",qPrint(yyextra->fileName));
 
   yyextra->current_root  = rt;
   yyextra->current = std::make_shared<Entry>();
-  int sec=guessSection(yyextra->yyFileName);
+  int sec=guessSection(yyextra->fileName);
   if (sec)
   {
-    yyextra->current->name    = yyextra->yyFileName;
+    yyextra->current->name    = yyextra->fileName;
     yyextra->current->section = sec;
     yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
   }
@@ -984,7 +988,7 @@ static void handleCCode(yyscan_t yyscanner)
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
 
   if (yyextra->cCodeBuffer.isEmpty()) return;
-  yyextra->cOutlineParser.parseInput(yyextra->yyFileName,
+  yyextra->cOutlineParser.parseInput(yyextra->fileName,
                                      yyextra->cCodeBuffer.data(),
                                      yyextra->current_root,
                                      yyextra->clangParser);
@@ -1019,6 +1023,7 @@ void LexOutlineParser::parseInput(const QCString &fileName,
 {
   struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
 
+  yyextra->fileName      = fileName;
   printlex(yy_flex_debug, TRUE, __FILE__, qPrint(fileName));
 
   ::parseMain(p->yyscanner,fileName,fileBuf,root,clangParser);
index 8d41d63..bb1169a 100644 (file)
@@ -166,6 +166,9 @@ void ManDocVisitor::visit(DocStyleChange *s)
     case DocStyleChange::Small:
       /* not supported */
       break;
+    case DocStyleChange::Cite:
+      /* not supported */
+      break;
     case DocStyleChange::Preformatted:
       if (s->enable())
       {
@@ -185,6 +188,18 @@ void ManDocVisitor::visit(DocStyleChange *s)
       break;
     case DocStyleChange::Div:  /* HTML only */ break;
     case DocStyleChange::Span: /* HTML only */ break;
+    case DocStyleChange::Details: /* emulation of the <details> tag */
+      if (!s->enable())
+      {
+        if (!m_firstCol) m_t << "\n";
+        m_t << ".PP\n";
+        m_firstCol=TRUE;
+      }
+      break;
+    case DocStyleChange::Summary: /* emulation of the <summary> tag inside a <details> tag */
+      if (s->enable()) m_t << "\\fB";      else m_t << "\\fP";
+      m_firstCol=FALSE;
+      break;
   }
 }
 
@@ -211,11 +226,19 @@ void ManDocVisitor::visit(DocVerbatim *s)
       m_t << ".PP\n";
       m_firstCol=TRUE;
       break;
+    case DocVerbatim::JavaDocLiteral:
+      filter(s->text());
+      break;
+    case DocVerbatim::JavaDocCode:
+      m_t << "\\fC\n";
+      filter(s->text());
+      m_t << "\\fP\n";
+      break;
     case DocVerbatim::Verbatim:
       if (!m_firstCol) m_t << "\n";
       m_t << ".PP\n";
       m_t << ".nf\n";
-      m_t << s->text();
+      filter(s->text());
       if (!m_firstCol) m_t << "\n";
       m_t << ".fi\n";
       m_t << ".PP\n";
@@ -685,6 +708,15 @@ void ManDocVisitor::visitPre(DocHtmlListItem *li)
   m_t << ".IP \"" << ws;
   if (((DocHtmlList *)li->parent())->type()==DocHtmlList::Ordered)
   {
+    for (const auto &opt : li->attribs())
+    {
+      if (opt.name=="value")
+      {
+        bool ok;
+        int val = opt.value.toInt(&ok);
+        if (ok) man_listItemInfo[m_indent].number = val;
+      }
+    }
     switch (man_listItemInfo[m_indent].type)
     {
       case '1':
index befea18..30c3f39 100644 (file)
@@ -126,7 +126,7 @@ class ManGenerator : public OutputGenerator
     void writeAnchor(const QCString &,const QCString &) {}
     void startCodeFragment(const QCString &);
     void endCodeFragment(const QCString &);
-    void writeLineNumber(const QCString &,const QCString &,const QCString &,int l) { m_t << l << " "; m_col=0; }
+    void writeLineNumber(const QCString &,const QCString &,const QCString &,int l, bool) { m_t << l << " "; m_col=0; }
     void startCodeLine(bool) {}
     void endCodeLine() { codify("\n"); m_col=0; }
     void startEmphasis() { m_t << "\\fI"; m_firstCol=FALSE; }
index 0c1db17..c8e6723 100644 (file)
 #include "fileinfo.h"
 #include "utf8.h"
 
+enum class ExplicitPageResult
+{
+  explicitPage,      /**< docs start with a page command */
+  explicitMainPage,  /**< docs start with a mainpage command */
+  notExplicit        /**< docs doesn't start with either page or mainpage */
+};
+
 #if !defined(NDEBUG)
 #define ENABLE_TRACING
 #endif
@@ -135,6 +142,11 @@ class Trace
       m_resultSet = true;
       m_resultValue = b ? "true" : "false";
     }
+    void setResult(ExplicitPageResult ep)
+    {
+      m_resultSet = true;
+      m_resultValue = QCString().setNum(static_cast<int>(ep));
+    }
     void setResult(int i)
     {
       m_resultSet = true;
@@ -194,7 +206,6 @@ int Trace::s_indent = 0;
   (data[i]=='('  || data[i]=='{' || data[i]=='[' || (data[i]=='<' && data[i+1]!='/') || \
    data[i]=='\\' || \
    data[i]=='@')
-
 //----------
 
 struct TableCell
@@ -280,8 +291,23 @@ static QCString escapeSpecialChars(const QCString &s)
     switch (c)
     {
       case '"':  if (pc!='\\')  { insideQuote=!insideQuote; } growBuf.addChar(c);   break;
-      case '<':  if (!insideQuote) { growBuf.addChar('\\'); } growBuf.addChar('<'); break;
-      case '>':  if (!insideQuote) { growBuf.addChar('\\'); } growBuf.addChar('>'); break;
+      case '<':
+      case '>':  if (!insideQuote)
+                 {
+                   growBuf.addChar('\\');
+                   growBuf.addChar(c);
+                   if ((p[0] == ':') && (p[1] == ':'))
+                   {
+                     growBuf.addChar('\\');
+                     growBuf.addChar(':');
+                     p++;
+                   }
+                 }
+                 else
+                 {
+                   growBuf.addChar(c);
+                 }
+                 break;
       case '\\': if (!insideQuote) { growBuf.addChar('\\'); } growBuf.addChar('\\'); break;
       case '@':  if (!insideQuote) { growBuf.addChar('\\'); } growBuf.addChar('@'); break;
       case '#':  if (!insideQuote) { growBuf.addChar('\\'); } growBuf.addChar('#'); break;
@@ -326,6 +352,29 @@ static Alignment markersToAlignment(bool leftMarker,bool rightMarker)
   }
 }
 
+/** parse the image attributes and return attributes for given format */
+static QCString getFilteredImageAttributes(const char *fmt, const QCString &attrs)
+{
+  StringVector attrList = split(attrs.str(),",");
+  for (const auto &attr_ : attrList)
+  {
+    QCString attr = QCString(attr_).stripWhiteSpace();
+    int i = attr.find(':');
+    if (i>0) // has format
+    {
+      QCString format = attr.left(i).stripWhiteSpace().lower();
+      if (format == fmt) // matching format
+      {
+        return attr.mid(i+1); // keep part after :
+      }
+    }
+    else // option that applies to all formats
+    {
+      return attr;
+    }
+  }
+  return QCString();
+}
 
 // Check if data contains a block command. If so returned the command
 // that ends the block. If not an empty string is returned.
@@ -341,14 +390,61 @@ static Alignment markersToAlignment(bool leftMarker,bool rightMarker)
 // \f[..\f]
 // \f{..\f}
 // \verbatim..\endverbatim
+// \iliteral..\endiliteral
 // \latexonly..\endlatexonly
 // \htmlonly..\endhtmlonly
 // \xmlonly..\endxmlonly
 // \rtfonly..\endrtfonly
 // \manonly..\endmanonly
+// \startuml..\enduml
 QCString Markdown::isBlockCommand(const char *data,int offset,int size)
 {
   TRACE(data);
+
+  using EndBlockFunc = QCString (*)(const std::string &,bool,char);
+
+  static const auto getEndBlock   = [](const std::string &blockName,bool,char) -> QCString
+  {
+    return "end"+blockName;
+  };
+  static const auto getEndCode    = [](const std::string &blockName,bool openBracket,char) -> QCString
+  {
+    return openBracket ? QCString("}") : "end"+blockName;
+  };
+  static const auto getEndUml     = [](const std::string &blockName,bool,char) -> QCString
+  {
+    return "enduml";
+  };
+  static const auto getEndFormula = [](const std::string &blockName,bool,char nextChar) -> QCString
+  {
+    switch (nextChar)
+    {
+      case '$': return "f$";
+      case '(': return "f)";
+      case '[': return "f]";
+      case '{': return "f}";
+    }
+    return "";
+  };
+
+  // table mapping a block start command to a function that can return the matching end block string
+  static const std::unordered_map<std::string,EndBlockFunc> blockNames =
+  {
+    { "dot",         getEndBlock   },
+    { "code",        getEndCode    },
+    { "msc",         getEndBlock   },
+    { "verbatim",    getEndBlock   },
+    { "iliteral",    getEndBlock   },
+    { "latexonly",   getEndBlock   },
+    { "htmlonly",    getEndBlock   },
+    { "xmlonly",     getEndBlock   },
+    { "rtfonly",     getEndBlock   },
+    { "manonly",     getEndBlock   },
+    { "docbookonly", getEndBlock   },
+    { "startuml",    getEndUml     },
+    { "f",           getEndFormula }
+  };
+
   bool openBracket = offset>0 && data[-1]=='{';
   bool isEscaped = offset>0 && (data[-1]=='\\' || data[-1]=='@');
   if (isEscaped) return QCString();
@@ -356,58 +452,208 @@ QCString Markdown::isBlockCommand(const char *data,int offset,int size)
   int end=1;
   while (end<size && (data[end]>='a' && data[end]<='z')) end++;
   if (end==1) return QCString();
-  QCString blockName;
-  convertStringFragment(blockName,data+1,end-1);
-  if (blockName=="code" && openBracket)
-  {
-    TRACE_RESULT("}");
-    return "}";
-  }
-  else if (blockName=="dot"         ||
-           blockName=="code"        ||
-           blockName=="msc"         ||
-           blockName=="verbatim"    ||
-           blockName=="latexonly"   ||
-           blockName=="htmlonly"    ||
-           blockName=="xmlonly"     ||
-           blockName=="rtfonly"     ||
-           blockName=="manonly"     ||
-           blockName=="docbookonly"
-     )
-  {
-    QCString result = "end"+blockName;
-    TRACE_RESULT(result);
-    return result;
-  }
-  else if (blockName=="startuml")
-  {
-    TRACE_RESULT("enduml");
-    return "enduml";
+  std::string blockName(data+1,end-1);
+  auto it = blockNames.find(blockName);
+  QCString result;
+  if (it!=blockNames.end()) // there is a function assigned
+  {
+    result = it->second(blockName, openBracket, end<size ? data[end] : 0);
   }
-  else if (blockName=="f" && end<size)
+  TRACE_RESULT(result);
+  return result;
+}
+
+int Markdown::isSpecialCommand(const char *data,int offset,int size)
+{
+  TRACE(data);
+
+  using EndCmdFunc = int (*)(const char *,int,int);
+
+  static const auto endOfLine = [](const char *data_,int offset_,int size_) -> int
+  {
+    // skip until the end of line (allowing line continuation characters)
+    char lc = 0;
+    char c;
+    while (offset_<size_ && ((c=data_[offset_])!='\n' || lc=='\\'))
+    {
+      if (c=='\\')     lc='\\'; // last character was a line continuation
+      else if (c!=' ') lc=0;    // rest line continuation
+      offset_++;
+    }
+    return offset_;
+  };
+
+  static const auto endOfLabel = [](const char *data_,int offset_,int size_) -> int
   {
-    if (data[end]=='$')
+    if (offset_<size_ && data_[offset_]==' ') // we expect a space before the label
     {
-      TRACE_RESULT("f$");
-      return "f$";
+      char c;
+      offset_++;
+      // skip over spaces
+      while (offset_<size_ && data_[offset_]==' ') offset_++;
+      // skip over label
+      while (offset_<size_ && (c=data_[offset_])!=' ' && c!='\n') offset_++;
+      return offset_;
     }
-    else if (data[end]=='(')
+    return 0;
+  };
+
+  static const auto endOfParam = [](const char *data_,int offset_,int size_) -> int
+  {
+    int index=offset_;
+    if (index<size_ && data_[index]==' ') // skip over optional spaces
     {
-      TRACE_RESULT("f)");
-      return "f)";
+      index++;
+      while (index<size_ && data_[index]==' ') index++;
     }
-    else if (data[end]=='[')
+    if (index<size_ && data_[index]=='[') // find matching ']'
     {
-      TRACE_RESULT("f]");
-      return "f]";
+      index++;
+      char c;
+      while (index<size_ && (c=data_[index])!=']' && c!='\n') index++;
+      if (index==size_ || data_[index]!=']') return 0; // invalid parameter
+      offset_=index+1; // part after [...] is the parameter name
     }
-    else if (data[end]=='{')
+    return endOfLabel(data_,offset_,size_);
+  };
+
+  static const auto endOfFunc = [](const char *data_,int offset_,int size_) -> int
+  {
+    if (offset_<size_ && data_[offset_]==' ') // we expect a space before the name
     {
-      TRACE_RESULT("f}");
-      return "f}";
+      char c=0;
+      offset_++;
+      // skip over spaces
+      while (offset_<size_ && data_[offset_]==' ') offset_++;
+      // skip over name
+      while (offset_<size_ && (c=data_[offset_])!=' ' && c!='\n' && c!='(') offset_++;
+      if (c=='(') // find the end of the function
+      {
+        int count=1;
+        offset_++;
+        while (offset_<size_ && (c=data_[offset_++]))
+        {
+          if      (c=='(') count++;
+          else if (c==')') count--;
+          if (count==0) return offset_;
+        }
+      }
+      return offset_;
     }
+    return 0;
+  };
+
+  static const auto endOfGuard = [](const char *data_,int offset_,int size_) -> int
+  {
+    return endOfFunc(data_,offset_,size_);
+  };
+
+  static const std::unordered_map<std::string,EndCmdFunc> cmdNames =
+  {
+    { "a",              endOfLabel },
+    { "addindex",       endOfLine  },
+    { "addtogroup",     endOfLabel },
+    { "anchor",         endOfLabel },
+    { "b",              endOfLabel },
+    { "c",              endOfLabel },
+    { "category",       endOfLine  },
+    { "cite",           endOfLabel },
+    { "class",          endOfLine  },
+    { "concept",        endOfLine  },
+    { "copybrief",      endOfFunc  },
+    { "copydetails",    endOfFunc  },
+    { "copydoc",        endOfFunc  },
+    { "def",            endOfFunc  },
+    { "defgroup",       endOfLabel },
+    { "diafile",        endOfLine  },
+    { "dir",            endOfLine  },
+    { "dockbookinclude",endOfLine  },
+    { "dontinclude",    endOfLine  },
+    { "dotfile",        endOfLine  },
+    { "dotfile",        endOfLine  },
+    { "e",              endOfLabel },
+    { "elseif",         endOfGuard },
+    { "em",             endOfLabel },
+    { "emoji",          endOfLabel },
+    { "enum",           endOfLabel },
+    { "example",        endOfLine  },
+    { "exception",      endOfLine  },
+    { "extends",        endOfLabel },
+    { "file",           endOfLine  },
+    { "fn",             endOfFunc  },
+    { "headerfile",     endOfLine  },
+    { "htmlinclude",    endOfLine  },
+    { "idlexcept",      endOfLine  },
+    { "if",             endOfGuard },
+    { "ifnot",          endOfGuard },
+    { "image",          endOfLine  },
+    { "implements",     endOfLine  },
+    { "include",        endOfLine  },
+    { "includedoc",     endOfLine  },
+    { "includelineno",  endOfLine  },
+    { "ingroup",        endOfLabel },
+    { "interface",      endOfLine  },
+    { "interface",      endOfLine  },
+    { "latexinclude",   endOfLine  },
+    { "maninclude",     endOfLine  },
+    { "memberof",       endOfLabel },
+    { "mscfile",        endOfLine  },
+    { "namespace",      endOfLabel },
+    { "noop",           endOfLine  },
+    { "overload",       endOfLine  },
+    { "p",              endOfLabel },
+    { "package",        endOfLabel },
+    { "page",           endOfLabel },
+    { "paragraph",      endOfLabel },
+    { "param",          endOfParam },
+    { "property",       endOfLine  },
+    { "protocol",       endOfLine  },
+    { "ref",            endOfLabel },
+    { "refitem",        endOfLabel },
+    { "related",        endOfLabel },
+    { "relatedalso",    endOfLabel },
+    { "relates",        endOfLabel },
+    { "relatesalso",    endOfLabel },
+    { "retval",         endOfLabel },
+    { "rtfinclude",     endOfLine  },
+    { "section",        endOfLabel },
+    { "skip",           endOfLine  },
+    { "skipline",       endOfLine  },
+    { "snippet",        endOfLine  },
+    { "snippetdoc",     endOfLine  },
+    { "snippetlineno",  endOfLine  },
+    { "struct",         endOfLine  },
+    { "subpage",        endOfLabel },
+    { "subsection",     endOfLabel },
+    { "subsubsection",  endOfLabel },
+    { "throw",          endOfLabel },
+    { "throws",         endOfLabel },
+    { "tparam",         endOfLabel },
+    { "typedef",        endOfLine  },
+    { "union",          endOfLine  },
+    { "until",          endOfLine  },
+    { "var",            endOfLine  },
+    { "verbinclude",    endOfLine  },
+    { "weakgroup",      endOfLabel },
+    { "xmlinclude",     endOfLine  },
+    { "xrefitem",       endOfLabel }
+  };
+
+  bool isEscaped = offset>0 && (data[-1]=='\\' || data[-1]=='@');
+  if (isEscaped) return 0;
+
+  int end=1;
+  while (end<size && (data[end]>='a' && data[end]<='z')) end++;
+  if (end==1) return 0;
+  std::string cmdName(data+1,end-1);
+  int result=0;
+  auto it = cmdNames.find(cmdName);
+  if (it!=cmdNames.end()) // command with parameters that should be ignored by markdown
+  {
+    // find the end of the parameters
+    result = it->second(data,end,size);
   }
-  return QCString();
+  return result;
 }
 
 /** looks for the next emph char, skipping other constructs, and
@@ -864,11 +1110,18 @@ int Markdown::processEmphasis(const char *data,int offset,int size)
   return 0;
 }
 
-void Markdown::writeMarkdownImage(const char *fmt, bool explicitTitle,
+void Markdown::writeMarkdownImage(const char *fmt, bool inline_img, bool explicitTitle,
                                   const QCString &title, const QCString &content,
-                                  const QCString &link, const FileDef *fd)
+                                  const QCString &link, const QCString &attrs,
+                                  const FileDef *fd)
 {
-  m_out.addStr("@image{inline} ");
+  QCString attributes = getFilteredImageAttributes(fmt, attrs);
+  m_out.addStr("@image");
+  if (inline_img)
+  {
+    m_out.addStr("{inline}");
+  }
+  m_out.addStr(" ");
   m_out.addStr(fmt);
   m_out.addStr(" ");
   m_out.addStr(link.mid(fd ? 0 : 5));
@@ -888,10 +1141,16 @@ void Markdown::writeMarkdownImage(const char *fmt, bool explicitTitle,
   {
     m_out.addStr(" ");// so the line break will not be part of the image name
   }
-  m_out.addStr("\\ilinebr");
+  if (!attributes.isEmpty())
+  {
+    m_out.addStr(" ");
+    m_out.addStr(attributes);
+    m_out.addStr(" ");
+  }
+  m_out.addStr("\\ilinebr ");
 }
 
-int Markdown::processLink(const char *data,int,int size)
+int Markdown::processLink(const char *data,int offset,int size)
 {
   TRACE(data);
   QCString content;
@@ -899,6 +1158,7 @@ int Markdown::processLink(const char *data,int,int size)
   QCString title;
   int contentStart,contentEnd,linkStart,titleStart,titleEnd;
   bool isImageLink = FALSE;
+  bool isImageInline = FALSE;
   bool isToc = FALSE;
   int i=1;
   if (data[0]=='!')
@@ -909,6 +1169,22 @@ int Markdown::processLink(const char *data,int,int size)
       TRACE_RESULT(0);
       return 0;
     }
+
+    // if there is non-whitespace before the ![ within the scope of two new lines, the image
+    // is considered inlined, i.e. the image is not preceded by an empty line
+    int numNLsNeeded=2;
+    int pos = -1;
+    while (pos>=-offset && numNLsNeeded>0)
+    {
+      if (data[pos]=='\n') numNLsNeeded--;
+      else if (data[pos]!=' ') // found non-whitespace, stop searching
+      {
+        isImageInline=true;
+        break;
+      }
+      pos--;
+    }
+    // skip '!['
     i++;
   }
   contentStart=i;
@@ -946,10 +1222,12 @@ int Markdown::processLink(const char *data,int,int size)
   if (!isImageLink && content.isEmpty()) { TRACE_RESULT(0); return 0; } // no link text
   i++; // skip over ]
 
+  bool whiteSpace = false;
   // skip whitespace
-  while (i<size && data[i]==' ') i++;
+  while (i<size && data[i]==' ') {whiteSpace = true; i++;}
   if (i<size && data[i]=='\n') // one newline allowed here
   {
+    whiteSpace = true;
     i++;
     nl++;
     // skip more whitespace
@@ -957,6 +1235,7 @@ int Markdown::processLink(const char *data,int,int size)
   }
   nlTotal += nl;
   nl = 0;
+  if (whiteSpace && i<size && (data[i]=='(' || data[i]=='[')) return 0;
 
   bool explicitTitle=FALSE;
   if (i<size && data[i]=='(') // inline link
@@ -1003,13 +1282,22 @@ int Markdown::processLink(const char *data,int,int size)
       i++;
       titleStart=i;
       nl=0;
-      while (i<size && data[i]!=')')
+      while (i<size)
       {
         if (data[i]=='\n')
         {
           if (nl>1) { TRACE_RESULT(0); return 0; }
           nl++;
         }
+        else if (data[i]=='\\') // escaped char in string
+        {
+          i++;
+        }
+        else if (data[i]==c)
+        {
+          i++;
+          break;
+        }
         i++;
       }
       if (i>=size)
@@ -1023,7 +1311,17 @@ int Markdown::processLink(const char *data,int,int size)
       if (data[titleEnd]==c) // found it
       {
         convertStringFragment(title,data+titleStart,titleEnd-titleStart);
-        //printf("processLink: title={%s}\n",qPrint(title));
+        explicitTitle=TRUE;
+        while (i<size)
+        {
+          if (data[i]==' ')i++; // remove space after the closing quote and the closing bracket
+          else if (data[i] == ')') break; // the end bracket
+          else // illegal
+          {
+            TRACE_RESULT(0);
+            return 0;
+          }
+        }
       }
       else
       {
@@ -1105,6 +1403,69 @@ int Markdown::processLink(const char *data,int,int size)
   }
   nlTotal += nl;
   nl = 0;
+
+  // search for optional image attributes
+  QCString attributes;
+  if (isImageLink)
+  {
+    int j = i;
+    // skip over whitespace
+    while (j<size && data[j]==' ') { j++; }
+    if (j<size && data[j]=='{') // we have attributes
+    {
+      i = j;
+      // skip over '{'
+      i++;
+      int attributesStart=i;
+      nl=0;
+      // find the matching '}'
+      while (i<size)
+      {
+        if (data[i-1]=='\\') // skip escaped characters
+        {
+        }
+        else if (data[i]=='{')
+        {
+          level++;
+        }
+        else if (data[i]=='}')
+        {
+          level--;
+          if (level<=0) break;
+        }
+        else if (data[i]=='\n')
+        {
+          nl++;
+          if (nl>1) { TRACE_RESULT(0); return 0; } // only allow one newline in the content
+        }
+        i++;
+      }
+      nlTotal += nl;
+      nl = 0;
+      if (i>=size) return 0; // premature end of comment -> no attributes
+      int attributesEnd=i;
+      convertStringFragment(attributes,data+attributesStart,attributesEnd-attributesStart);
+      i++; // skip over '}'
+    }
+    if (!isImageInline)
+    {
+      // if there is non-whitespace after the image within the scope of two new lines, the image
+      // is considered inlined, i.e. the image is not followed by an empty line
+      int numNLsNeeded=2;
+      int pos = i;
+      while (pos<size && numNLsNeeded>0)
+      {
+        if (data[pos]=='\n') numNLsNeeded--;
+        else if (data[pos]!=' ') // found non-whitespace, stop searching
+        {
+          isImageInline=true;
+          break;
+        }
+        pos++;
+      }
+    }
+  }
+
   if (isToc) // special case for [TOC]
   {
     int toc_level = Config_getInt(TOC_INCLUDE_HEADINGS);
@@ -1123,10 +1484,11 @@ int Markdown::processLink(const char *data,int,int size)
         (fd=findFileDef(Doxygen::imageNameLinkedMap,link,ambig)))
         // assume doxygen symbol link or local image link
     {
-      writeMarkdownImage("html",    explicitTitle, title, content, link, fd);
-      writeMarkdownImage("latex",   explicitTitle, title, content, link, fd);
-      writeMarkdownImage("rtf",     explicitTitle, title, content, link, fd);
-      writeMarkdownImage("docbook", explicitTitle, title, content, link, fd);
+      // check if different handling is needed per format
+      writeMarkdownImage("html",    isImageInline, explicitTitle, title, content, link, attributes, fd);
+      writeMarkdownImage("latex",   isImageInline, explicitTitle, title, content, link, attributes, fd);
+      writeMarkdownImage("rtf",     isImageInline, explicitTitle, title, content, link, attributes, fd);
+      writeMarkdownImage("docbook", isImageInline, explicitTitle, title, content, link, attributes, fd);
     }
     else
     {
@@ -1177,32 +1539,44 @@ int Markdown::processLink(const char *data,int,int size)
       m_out.addStr(" \"");
       if (explicitTitle && !title.isEmpty())
       {
-        m_out.addStr(title);
+        m_out.addStr(substitute(title,"\"","&quot;"));
       }
       else
       {
-        m_out.addStr(content);
+        m_out.addStr(substitute(content,"\"","&quot;"));
       }
       m_out.addStr("\"");
     }
     else if (link.find('/')!=-1 || link.find('.')!=-1 || link.find('#')!=-1)
     { // file/url link
-      m_out.addStr("<a href=\"");
-      m_out.addStr(link);
-      m_out.addStr("\"");
-      for (int ii = 0; ii < nlTotal; ii++) m_out.addStr("\n");
-      if (!title.isEmpty())
+      if (link.at(0) == '#')
       {
-        m_out.addStr(" title=\"");
-        m_out.addStr(substitute(title.simplifyWhiteSpace(),"\"","&quot;"));
+        m_out.addStr("@ref ");
+        m_out.addStr(link.mid(1));
+        m_out.addStr(" \"");
+        m_out.addStr(substitute(content.simplifyWhiteSpace(),"\"","&quot;"));
         m_out.addStr("\"");
+
+      }
+      else
+      {
+        m_out.addStr("<a href=\"");
+        m_out.addStr(link);
+        m_out.addStr("\"");
+        for (int ii = 0; ii < nlTotal; ii++) m_out.addStr("\n");
+        if (!title.isEmpty())
+        {
+          m_out.addStr(" title=\"");
+          m_out.addStr(substitute(title.simplifyWhiteSpace(),"\"","&quot;"));
+          m_out.addStr("\"");
+        }
+        m_out.addStr(" ");
+        m_out.addStr(externalLinkTarget());
+        m_out.addStr(">");
+        content = substitute(content.simplifyWhiteSpace(),"\"","\\\"");
+        processInline(content.data(),content.length());
+        m_out.addStr("</a>");
       }
-      m_out.addStr(" ");
-      m_out.addStr(externalLinkTarget());
-      m_out.addStr(">");
-      content = content.simplifyWhiteSpace();
-      processInline(content.data(),content.length());
-      m_out.addStr("</a>");
     }
     else // avoid link to e.g. F[x](y)
     {
@@ -1332,7 +1706,13 @@ int Markdown::processSpecialCommand(const char *data, int offset, int size)
       i++;
     }
   }
-  if (size>1 && data[0]=='\\')
+  int endPos = isSpecialCommand(data,offset,size);
+  if (endPos>0)
+  {
+    m_out.addStr(data,endPos);
+    return endPos;
+  }
+  if (size>1 && data[0]=='\\') // escaped characters
   {
     char c=data[1];
     if (c=='[' || c==']' || c=='*' || c=='!' || c=='(' || c==')' || c=='`' || c=='_')
@@ -1365,16 +1745,19 @@ void Markdown::processInline(const char *data,int size)
   Action_t action;
   while (i<size)
   {
+    // skip over character that do not trigger a specific action
     while (end<size && ((action=m_actions[(uchar)data[end]])==0)) end++;
+    // and add them to the output
     m_out.addStr(data+i,end-i);
     if (end>=size) break;
     i=end;
+    // do the action matching a special character at i
     end = action(data+i,i,size-i);
-    if (end<=0)
+    if (end<=0) // update end
     {
       end=i+1-end;
     }
-    else
+    else // skip until end
     {
       i+=end;
       end=i;
@@ -1434,8 +1817,8 @@ bool isBlockQuote(const char *data,int size,int indent)
       i++;
     }
     // last characters should be a space or newline,
-    // so a line starting with >= does not match
-    bool res = level>0 && i<size && ((data[i-1]==' ') || data[i]=='\n');
+    // so a line starting with >= does not match, but only when level equals 1
+    bool res = (level>0 && i<size && ((data[i-1]==' ') || data[i]=='\n')) || (level > 1);
     TRACE_RESULT(res);
     return res;
   }
@@ -1584,7 +1967,7 @@ static QCString extractTitleId(QCString &title, int level)
     title = title.left((int)match.position());
     //printf("found match id='%s' title=%s\n",id.c_str(),qPrint(title));
     TRACE_RESULT(QCString(id));
-    return id;
+    return QCString(id);
   }
   if ((level > 0) && (level <= Config_getInt(TOC_INCLUDE_HEADINGS)))
   {
@@ -2166,6 +2549,15 @@ int Markdown::writeTableBlock(const char *data,int size)
       {
         continue;
       }
+      if (tableContents[row][c].colSpan)
+      {
+        int cr = c;
+        while ( cr >= 0 && tableContents[row][cr].colSpan)
+        {
+          cr--;
+        };
+        if (cr >= 0 && tableContents[row][cr].cellText == "^") continue;
+      }
       unsigned rowSpan = 1, spanRow = row+1;
       while ((spanRow < tableContents.size()) &&
              (tableContents[spanRow][c].cellText == "^"))
@@ -2322,14 +2714,17 @@ int Markdown::writeBlockQuote(const char *data,int size)
         !(j==size || data[j]=='\n')) // disqualify last > if not followed by space
     {
       indent--;
+      level--;
       j--;
     }
+    if (!level && data[j-1]!='\n') level=curLevel; // lazy
     if (level>curLevel) // quote level increased => add start markers
     {
-      for (l=curLevel;l<level;l++)
+      for (l=curLevel;l<level-1;l++)
       {
         m_out.addStr("<blockquote>");
       }
+      m_out.addStr("<blockquote>&zwj;"); // empty blockquotes are also shown
     }
     else if (level<curLevel) // quote level decreased => add end markers
     {
@@ -2452,7 +2847,7 @@ void Markdown::findEndOfLine(const char *data,int size,
             )
     {
       if (tolower(data[end])=='p' && tolower(data[end+1])=='r' &&
-          tolower(data[end+2])=='e' && data[end+3]=='>') // <pre> tag
+          tolower(data[end+2])=='e' && (data[end+3]=='>' || data[end+3]==' ')) // <pre> tag
       {
         // skip part until including </pre>
         end  = end + processHtmlTagWrite(data+end-1,end-1,size-end+1,false) + 2;
@@ -2825,8 +3220,8 @@ QCString Markdown::processBlocks(const QCString &s,const int indent)
   return m_out.get();
 }
 
-/** returns TRUE if input string docs starts with \@page or \@mainpage command */
-static bool isExplicitPage(const QCString &docs)
+
+static ExplicitPageResult isExplicitPage(const QCString &docs)
 {
   TRACE(docs);
   int i=0;
@@ -2843,12 +3238,20 @@ static bool isExplicitPage(const QCString &docs)
         (qstrncmp(&data[i+1],"page ",5)==0 || qstrncmp(&data[i+1],"mainpage",8)==0)
        )
     {
-      TRACE_RESULT(TRUE);
-      return TRUE;
+      if (qstrncmp(&data[i+1],"page ",5)==0)
+      {
+        TRACE_RESULT(ExplicitPageResult::explicitPage);
+        return ExplicitPageResult::explicitPage;
+      }
+      else
+      {
+        TRACE_RESULT(ExplicitPageResult::explicitMainPage);
+        return ExplicitPageResult::explicitMainPage;
+      }
     }
   }
-  TRACE_RESULT(FALSE);
-  return FALSE;
+  TRACE_RESULT(ExplicitPageResult::notExplicit);
+  return ExplicitPageResult::notExplicit;
 }
 
 QCString Markdown::extractPageTitle(QCString &docs,QCString &id, int &prepend)
@@ -3083,30 +3486,55 @@ void MarkdownOutlineParser::parseInput(const QCString &fileName,
   QCString mdfileAsMainPage = Config_getString(USE_MDFILE_AS_MAINPAGE);
   bool wasEmpty = id.isEmpty();
   if (wasEmpty) id = markdownFileNameToId(fileName);
-  if (!isExplicitPage(docs))
+  switch (isExplicitPage(docs))
   {
-    if (!mdfileAsMainPage.isEmpty() &&
-        (fn==mdfileAsMainPage || // name reference
-         FileInfo(fileName.str()).absFilePath()==
-         FileInfo(mdfileAsMainPage.str()).absFilePath()) // file reference with path
-       )
-    {
-      docs.prepend("@anchor " + id + "\\ilinebr ");
-      docs.prepend("@mainpage "+title+"\\ilinebr ");
-    }
-    else if (id=="mainpage" || id=="index")
-    {
-      if (title.isEmpty()) title = titleFn;
-      docs.prepend("@anchor " + id + "\\ilinebr ");
-      docs.prepend("@mainpage "+title+"\\ilinebr ");
-    }
-    else
-    {
-      if (title.isEmpty()) {title = titleFn;prepend=0;}
-      if (!wasEmpty) docs.prepend("@anchor " +  markdownFileNameToId(fileName) + "\\ilinebr ");
-      docs.prepend("@page "+id+" "+title+"\\ilinebr ");
-    }
-    for (int i = 0; i < prepend; i++) docs.prepend("\n");
+    case ExplicitPageResult::notExplicit:
+      if (!mdfileAsMainPage.isEmpty() &&
+          (fn==mdfileAsMainPage || // name reference
+           FileInfo(fileName.str()).absFilePath()==
+           FileInfo(mdfileAsMainPage.str()).absFilePath()) // file reference with path
+         )
+      {
+        docs.prepend("@anchor " + id + "\\ilinebr ");
+        docs.prepend("@mainpage "+title+"\\ilinebr ");
+      }
+      else if (id=="mainpage" || id=="index")
+      {
+        if (title.isEmpty()) title = titleFn;
+        docs.prepend("@anchor " + id + "\\ilinebr ");
+        docs.prepend("@mainpage "+title+"\\ilinebr ");
+      }
+      else
+      {
+        if (title.isEmpty()) {title = titleFn;prepend=0;}
+        if (!wasEmpty) docs.prepend("@anchor " +  markdownFileNameToId(fileName) + "\\ilinebr ");
+        docs.prepend("@page "+id+" "+title+"\\ilinebr ");
+      }
+      for (int i = 0; i < prepend; i++) docs.prepend("\n");
+      break;
+    case ExplicitPageResult::explicitPage:
+      {
+        // look for `@page label Title\n` and capture `label`
+        static const reg::Ex re(R"([\\@]page\s+(\a[\w-]*)\s*[^\n]*\n)");
+        reg::Match match;
+        std::string s = docs.str();
+        if (reg::search(s,match,re))
+        {
+          QCString orgLabel    = match[1].str();
+          QCString newLabel    = markdownFileNameToId(fileName);
+          size_t labelStartPos = match[1].position();
+          size_t labelEndPos   = labelStartPos+match[1].length();
+          size_t lineLen       = match.length();
+          docs = docs.left(labelStartPos)+                     // part before label
+                 newLabel+                                     // new label
+                 docs.mid(labelEndPos,lineLen-labelEndPos-1)+  // part between orgLabel and \n
+                 "\\ilinebr @anchor "+orgLabel+"\n"+           // add original anchor
+                 docs.right(docs.length()-match.length());     // add remainder of docs
+        }
+      }
+      break;
+    case ExplicitPageResult::explicitMainPage:
+      break;
   }
   int lineNr=1;
 
index 9d5343c..e3625c5 100644 (file)
@@ -42,6 +42,7 @@ class Markdown
     QCString processQuotations(const QCString &s,int refIndent);
     QCString processBlocks(const QCString &s,int indent);
     QCString isBlockCommand(const char *data,int offset,int size);
+    int isSpecialCommand(const char *data,int offset,int size);
     void findEndOfLine(const char *data,int size,int &pi,int&i,int &end);
     int processHtmlTagWrite(const char *data,int offset,int size,bool doWrite);
     int processHtmlTag(const char *data,int offset,int size);
@@ -57,9 +58,10 @@ class Markdown
     int processLink(const char *data,int,int size);
     int findEmphasisChar(const char *data, int size, char c, int c_size);
     void processInline(const char *data,int size);
-    void writeMarkdownImage(const char *fmt, bool explicitTitle,
+    void writeMarkdownImage(const char *fmt, bool inline_img, bool explicitTitle,
                             const QCString &title, const QCString &content,
-                            const QCString &link, const FileDef *fd);
+                            const QCString &link, const QCString &attributes,
+                            const FileDef *fd);
     int isHeaderline(const char *data, int size, bool allowAdjustLevel);
     int isAtxHeader(const char *data,int size,
                        QCString &header,QCString &id,bool allowAdjustLevel);
index d0cb7da..6dd51ea 100644 (file)
@@ -163,6 +163,7 @@ class MemberDefImpl : public DefinitionMixin<MemberDefMutable>
     virtual bool isTemplateSpecialization() const;
     virtual bool isObjCMethod() const;
     virtual bool isObjCProperty() const;
+    virtual bool isCSharpProperty() const;
     virtual bool isConstructor() const;
     virtual bool isDestructor() const;
     virtual bool hasOneLineInitializer() const;
@@ -312,7 +313,7 @@ class MemberDefImpl : public DefinitionMixin<MemberDefMutable>
     virtual void incrementFlowKeyWordCount();
     virtual void writeDeclaration(OutputList &ol,
                    const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
-                   bool inGroup, const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const;
+                   bool inGroup, int indentLevel,const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const;
     virtual void writeDocumentation(const MemberList *ml,int memCount,int memTotal,OutputList &ol,
                             const QCString &scopeName,const Definition *container,
                             bool inGroup,bool showEnumValues=FALSE,bool
@@ -331,7 +332,6 @@ class MemberDefImpl : public DefinitionMixin<MemberDefMutable>
     virtual void writeLink(OutputList &ol,
                    const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
                    bool onlyText=FALSE) const;
-    virtual void addToSearchIndex() const;
     virtual void resolveUnnamedParameters(const MemberDef *md);
 
   private:
@@ -358,8 +358,6 @@ class MemberDefImpl : public DefinitionMixin<MemberDefMutable>
     bool _hasVisibleCallGraph() const;
     bool _hasVisibleCallerGraph() const;
 
-    static int s_indentLevel;
-
     // disable copying of member defs
     MemberDefImpl(const MemberDefImpl &);
     MemberDefImpl &operator=(const MemberDefImpl &);
@@ -604,6 +602,8 @@ class MemberDefAliasImpl : public DefinitionAliasMixin<MemberDef>
     { return getMdAlias()->isObjCMethod(); }
     virtual bool isObjCProperty() const
     { return getMdAlias()->isObjCProperty(); }
+    virtual bool isCSharpProperty() const
+    { return getMdAlias()->isCSharpProperty(); }
     virtual bool isConstructor() const
     { return getMdAlias()->isConstructor(); }
     virtual bool isDestructor() const
@@ -767,9 +767,9 @@ class MemberDefAliasImpl : public DefinitionAliasMixin<MemberDef>
 
     virtual void writeDeclaration(OutputList &ol,
                    const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
-                   bool inGroup, const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const
+                   bool inGroup, int indentLevel, const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const
     {
-      getMdAlias()->writeDeclaration(ol,cd,nd,fd,gd,inGroup,inheritFrom,inheritId);
+      getMdAlias()->writeDeclaration(ol,cd,nd,fd,gd,inGroup,indentLevel,inheritFrom,inheritId);
     }
     virtual void writeEnumDeclaration(OutputList &typeDecl,
             const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const
@@ -790,10 +790,6 @@ MemberDef *createMemberDefAlias(const Definition *newScope,const MemberDef *alia
 
 //-----------------------------------------------------------------------------
 
-int MemberDefImpl::s_indentLevel = 0;
-
-//-----------------------------------------------------------------------------
-
 static QCString addTemplateNames(const QCString &s,const QCString &n,const QCString &t)
 {
   QCString result;
@@ -1826,11 +1822,14 @@ void MemberDefImpl::writeLink(OutputList &ol,
   }
 }
 
+static std::mutex g_cachedAnonymousTypeMutex;
+
 /*! 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() const
 {
+  std::lock_guard<std::mutex> lock(g_cachedAnonymousTypeMutex);
   //printf("%s:getClassDefOfAnonymousType() cache=%s\n",qPrint(name()),
   //                   m_impl->cachedAnonymousType?qPrint(m_impl->cachedAnonymousType->name()):"<empty>");
   if (m_impl->cachedAnonymousType) return m_impl->cachedAnonymousType;
@@ -2066,9 +2065,9 @@ void MemberDefImpl::_writeTemplatePrefix(OutputList &ol, const Definition *def,
 
 void MemberDefImpl::writeDeclaration(OutputList &ol,
                const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
-               bool inGroup, const ClassDef *inheritedFrom,const QCString &inheritId) const
+               bool inGroup, int indentLevel, const ClassDef *inheritedFrom,const QCString &inheritId) const
 {
-  //printf("%s MemberDefImpl::writeDeclaration() inGroup=%d\n",qPrint(qualifiedName()),inGroup);
+  //printf("%s MemberDefImpl::writeDeclaration() inGroup=%d\n",qPrint(qualifiedName()),inGroup);
 
   // hide enum value, since they appear already as part of the enum, unless they
   // are explicitly grouped.
@@ -2085,8 +2084,6 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
     else if (getFileDef())      d = getFileDef();
   }
 
-  addToSearchIndex();
-
   QCString cname  = d->name();
   QCString cdname = d->displayName();
   QCString cfname = getOutputFileBase();
@@ -2131,7 +2128,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
   if (annoClassDef || m_impl->annMemb)
   {
     int j;
-    for (j=0;j<s_indentLevel;j++)
+    for (j=0;j<indentLevel;j++)
     {
       ol.writeNonBreakableSpace(3);
     }
@@ -2173,12 +2170,12 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
     {
       int ir=i+l;
       //printf("<<<<<<<<<<<<<<\n");
-      ol.startAnonTypeScope(s_indentLevel++);
-      annoClassDef->writeDeclaration(ol,m_impl->annMemb,inGroup,inheritedFrom,inheritId);
+      ol.startAnonTypeScope(indentLevel);
+      annoClassDef->writeDeclaration(ol,m_impl->annMemb,inGroup,indentLevel+1,inheritedFrom,inheritId);
       //printf(">>>>>>>>>>>>>> startMemberItem(2)\n");
       ol.startMemberItem(anchor(),2,inheritId);
       int j;
-      for (j=0;j< s_indentLevel-1;j++)
+      for (j=0;j< indentLevel;j++)
       {
         ol.writeNonBreakableSpace(3);
       }
@@ -2320,26 +2317,6 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
     }
   }
 
-  // add to index
-  if (isEnumerate() && isAnonymous())
-  {
-    // don't add to index
-  }
-  else // index member
-  {
-    //static bool separateMemPages = Config_getBool(SEPARATE_MEMBER_PAGES);
-    //QCString cfname = getOutputFileBase();
-    //QCString cfiname = d->getOutputFileBase();
-    //Doxygen::indexList->addIndexItem(
-    //    cname,                                 // level1
-    //    name(),                                // level2
-    //    separateMemPages ? cfname : cfiname,   // contRef
-    //    cfname,                                // memRef
-    //    anchor(),                              // anchor
-    //    this);                                 // memberdef
-    Doxygen::indexList->addIndexItem(d,this);
-  }
-
   // *** write arguments
   if (!argsString().isEmpty() && !isObjCMethod())
   {
@@ -2356,7 +2333,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
                 m_impl->annMemb,         // autoBreak
                 TRUE,                    // external
                 FALSE,                   // keepSpaces
-                s_indentLevel
+                indentLevel
                );
   }
   // *** write exceptions
@@ -2428,8 +2405,8 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
          if (!first)
          {
            ol.docify(", ");
-           first=false;
          }
+         first=false;
          ol.docify(s.c_str());
       }
       ol.docify("]");
@@ -2451,8 +2428,8 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
         if (!first)
         {
           ol.docify(", ");
-          first=false;
         }
+        first=false;
         ol.docify(s.c_str());
       }
       ol.docify("]");
@@ -2469,7 +2446,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
   ol.endMemberItem();
   if (endAnonScopeNeeded)
   {
-    ol.endAnonTypeScope(--s_indentLevel);
+    ol.endAnonTypeScope(indentLevel);
   }
 
   // write brief description
@@ -2511,6 +2488,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
   ol.endMemberDeclaration(anchor(),inheritId);
 
   warnIfUndocumented();
+  //printf("< %s MemberDefImpl::writeDeclaration() inGroup=%d\n",qPrint(qualifiedName()),inGroup);
 }
 
 bool MemberDefImpl::hasDetailedDescription() const
@@ -3047,8 +3025,6 @@ void MemberDefImpl::_writeEnumValues(OutputList &ol,const Definition *container,
         ol.addIndexItem(fmd->name(),ciname);
         ol.addIndexItem(ciname,fmd->name());
 
-        Doxygen::indexList->addIndexItem(container,fmd);
-
         ol.startDescTableTitle();
         ol.startDoxyAnchor(cfname,cname,fmd->anchor(),fmd->name(),fmd->argsString());
         first=FALSE;
@@ -3734,7 +3710,7 @@ static QCString simplifyTypeForTable(const QCString &s)
     t = match.prefix().str() + match.suffix().str(); // remove the matched part
   }
   //printf("simplifyTypeForTable(%s)->%s\n",qPrint(s),t.c_str());
-  return t;
+  return QCString(t);
 }
 
 QCString MemberDefImpl::fieldType() const
@@ -3946,7 +3922,6 @@ static QCString stripTrailingReturn(const QCString &trailRet)
 
 void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const
 {
-  if (!Config_getBool(WARN_NO_PARAMDOC)) return;
   QCString returnType = typeString();
   bool isPython = getLanguage()==SrcLangExt_Python;
   bool isFortran = getLanguage()==SrcLangExt_Fortran;
@@ -4030,7 +4005,8 @@ void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturn
             )
           )
   {
-    warn_doc_error(getDefFileName(),getDefLine(),"documented empty return type of %s",
+
+    warn_doc_error(docFile(),docLine(),"documented empty return type of %s",
                           qPrint(qualifiedName()));
   }
   else if ( // see if return needs to documented
@@ -4058,14 +4034,14 @@ void MemberDefImpl::warnIfUndocumentedParams() const
     QCString returnType = typeString();
     if (!m_impl->hasDocumentedParams)
     {
-      warn_doc_error(getDefFileName(),getDefLine(),
+      warn_doc_error(docFile(),docLine(),
           "parameters of member %s are not (all) documented",
           qPrint(qualifiedName()));
     }
     if (!m_impl->hasDocumentedReturnType &&
         hasDocumentation() && !returnType.isEmpty())
     {
-      warn_doc_error(getDefFileName(),getDefLine(),
+      warn_doc_error(docFile(),docLine(),
           "return type of member %s is not documented",
           qPrint(qualifiedName()));
     }
@@ -4395,7 +4371,7 @@ void MemberDefImpl::writeTagFile(TextStream &tagFile) const
     tagFile << "      <type>" << convertToXML(typeString()) << "</type>\n";
   }
   tagFile << "      <name>" << convertToXML(name()) << "</name>\n";
-  tagFile << "      <anchorfile>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</anchorfile>\n";
+  tagFile << "      <anchorfile>" << addHtmlExtensionIfMissing(getOutputFileBase()) << "</anchorfile>\n";
   tagFile << "      <anchor>" << convertToXML(anchor()) << "</anchor>\n";
   QCString idStr = id();
   if (!idStr.isEmpty())
@@ -4409,7 +4385,7 @@ void MemberDefImpl::writeTagFile(TextStream &tagFile) const
     {
       if (!fmd->isReference())
       {
-        tagFile << "      <enumvalue file=\"" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension);
+        tagFile << "      <enumvalue file=\"" << convertToXML(addHtmlExtensionIfMissing(getOutputFileBase()));
         tagFile << "\" anchor=\"" << convertToXML(fmd->anchor());
         idStr = fmd->id();
         if (!idStr.isEmpty())
@@ -4533,7 +4509,6 @@ void MemberDefImpl::writeEnumDeclaration(OutputList &typeDecl,
     if (isLinkableInProject() || hasDocumentedEnumValues())
     {
       //_writeTagData(compoundType);
-      addToSearchIndex();
       writeLink(typeDecl,cd,nd,fd,gd);
     }
     else
@@ -4590,7 +4565,6 @@ void MemberDefImpl::writeEnumDeclaration(OutputList &typeDecl,
           MemberDefMutable *fmdm = toMemberDefMutable(fmd);
           if (fmdm && fmd->hasDocumentation()) // enum value has docs
           {
-            fmdm->addToSearchIndex();
             fmdm->writeLink(typeDecl,cd,nd,fd,gd);
           }
           else // no docs for this enum value
@@ -4732,6 +4706,12 @@ bool MemberDefImpl::isObjCProperty() const
   return FALSE;
 }
 
+bool MemberDefImpl::isCSharpProperty() const
+{
+  if (getClassDef() && getClassDef()->isCSharp() && isProperty()) return TRUE;
+  return FALSE;
+}
+
 QCString MemberDefImpl::qualifiedName() const
 {
   if (isObjCMethod())
@@ -5812,31 +5792,6 @@ QCString MemberDefImpl::displayName(bool) const
   return DefinitionMixin::name();
 }
 
-void MemberDefImpl::addToSearchIndex() const
-{
-  // write search index info
-  if (Doxygen::searchIndex && isLinkableInProject())
-  {
-    Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
-    QCString ln=localName(),qn=qualifiedName();
-    Doxygen::searchIndex->addWord(ln,TRUE);
-    if (ln!=qn)
-    {
-      Doxygen::searchIndex->addWord(qn,TRUE);
-      if (getClassDef())
-      {
-        Doxygen::searchIndex->addWord(getClassDef()->displayName(),TRUE);
-      }
-      else if (getNamespaceDef())
-      {
-        Doxygen::searchIndex->addWord(getNamespaceDef()->displayName(),TRUE);
-      }
-    }
-  }
-}
-
-
-
 //----------------
 
 static void transferArgumentDocumentation(ArgumentList &decAl,ArgumentList &defAl)
@@ -5881,9 +5836,12 @@ void combineDeclarationAndDefinition(MemberDefMutable *mdec,MemberDefMutable *md
     //    mdef, mdef ? qPrint(mdef->name()) : "",
     //    mdec, mdec ? qPrint(mdec->name()) : "");
 
+    bool sameNumTemplateArgs = mdef->templateArguments().size()==mdec->templateArguments().size();
+
     ArgumentList &mdefAl = const_cast<ArgumentList&>(mdef->argumentList());
     ArgumentList &mdecAl = const_cast<ArgumentList&>(mdec->argumentList());
-    if (matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),&mdefAl,
+    if (sameNumTemplateArgs &&
+        matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),&mdefAl,
                         mdec->getOuterScope(),mdec->getFileDef(),&mdecAl,
                         TRUE
                        )
index a3b8293..46c2479 100644 (file)
@@ -172,6 +172,7 @@ class MemberDef : public Definition
     virtual bool isTemplateSpecialization() const = 0;
     virtual bool isObjCMethod() const = 0;
     virtual bool isObjCProperty() const = 0;
+    virtual bool isCSharpProperty() const = 0;
     virtual bool isConstructor() const = 0;
     virtual bool isDestructor() const = 0;
     virtual bool hasOneLineInitializer() const = 0;
@@ -280,7 +281,7 @@ class MemberDef : public Definition
                const std::unique_ptr<ArgumentList> &actualArgs) const = 0;
     virtual void writeDeclaration(OutputList &ol,
                  const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
-                 bool inGroup, const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const = 0;
+                 bool inGroup, int indentLevel=0, const ClassDef *inheritFrom=0,const QCString &inheritId=QCString()) const = 0;
     virtual void writeEnumDeclaration(OutputList &typeDecl, const ClassDef *cd,
                 const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const = 0;
     virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const = 0;
@@ -407,7 +408,7 @@ class MemberDefMutable : public DefinitionMutable, public MemberDef
     //-----------------------------------------------------------------------------------
 
     virtual void findSectionsInDocumentation() = 0;
-    virtual void addToSearchIndex() const = 0;
+    //virtual void addToSearchIndex() const = 0;
 
     //-----------------------------------------------------------------------------------
     // --- write output ----
index 5ed1030..6cfce97 100644 (file)
@@ -101,11 +101,11 @@ void MemberGroup::writeDeclarations(OutputList &ol,
 
 void MemberGroup::writePlainDeclarations(OutputList &ol,bool inGroup,
                const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
-               const ClassDef *inheritedFrom,const QCString &inheritId
+               int indentLevel,const ClassDef *inheritedFrom,const QCString &inheritId
               ) const
 {
   //printf("MemberGroup::writePlainDeclarations() memberList->count()=%d\n",memberList->count());
-  memberList->writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,inheritedFrom,inheritId);
+  memberList->writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,indentLevel,inheritedFrom,inheritId);
 }
 
 void MemberGroup::writeDocumentation(OutputList &ol,const QCString &scopeName,
@@ -140,7 +140,7 @@ void MemberGroup::addGroupedInheritedMembers(OutputList &ol,const ClassDef *cd,
       MemberList mml(lt,MemberListContainer::Class);
       mml.push_back(md);
       mml.countDecMembers();
-      mml.writePlainDeclarations(ol,false,cd,0,0,0,inheritedFrom,inheritId);
+      mml.writePlainDeclarations(ol,false,cd,0,0,0,0,inheritedFrom,inheritId);
     }
   }
 }
index 7fbafaa..8fbe56c 100644 (file)
@@ -51,7 +51,7 @@ class MemberGroup
     void setAnchors();
     void writePlainDeclarations(OutputList &ol,bool inGroup,
                const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
-               const ClassDef *inheritedFrom,const QCString &inheritId) const;
+               int indentLevel, const ClassDef *inheritedFrom,const QCString &inheritId) const;
     void writeDeclarations(OutputList &ol,
                const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
                bool showInline=FALSE) const;
index 989eb48..23a02df 100644 (file)
@@ -325,8 +325,8 @@ bool MemberList::declVisible() const
 }
 
 void MemberList::writePlainDeclarations(OutputList &ol, bool inGroup,
-                       const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,
-                       const GroupDef *gd,const ClassDef *inheritedFrom,const QCString &inheritId
+                       const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd, const GroupDef *gd,
+                       int indentLevel, const ClassDef *inheritedFrom,const QCString &inheritId
                       ) const
 {
   //printf("----- writePlainDeclaration() ----\n");
@@ -372,7 +372,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, bool inGroup,
         case MemberType_Event:
           {
             if (first) ol.startMemberList(),first=FALSE;
-            md->writeDeclaration(ol,cd,nd,fd,gd,inGroup,inheritedFrom,inheritId);
+            md->writeDeclaration(ol,cd,nd,fd,gd,inGroup,indentLevel,inheritedFrom,inheritId);
             break;
           }
         case MemberType_Enumeration:
@@ -457,7 +457,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, bool inGroup,
               ol.startMemberList();
               first=FALSE;
             }
-            md->writeDeclaration(ol,cd,nd,fd,gd,inGroup,inheritedFrom,inheritId);
+            md->writeDeclaration(ol,cd,nd,fd,gd,inGroup,indentLevel,inheritedFrom,inheritId);
             break;
           }
         case MemberType_EnumValue:
@@ -466,7 +466,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, bool inGroup,
             {
               //printf("EnumValue!\n");
               if (first) ol.startMemberList(),first=FALSE;
-              md->writeDeclaration(ol,cd,nd,fd,gd,true,inheritedFrom,inheritId);
+              md->writeDeclaration(ol,cd,nd,fd,gd,true,indentLevel,inheritedFrom,inheritId);
             }
           }
           break;
@@ -492,7 +492,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, bool inGroup,
             ol.startMemberList();
             first=FALSE;
           }
-          md->writeDeclaration(ol,cd,nd,fd,gd,inGroup);
+          md->writeDeclaration(ol,cd,nd,fd,gd,inGroup,indentLevel);
         }
         if (mdm) mdm->setFromAnonymousScope(TRUE);
       }
@@ -608,7 +608,7 @@ void MemberList::writeDeclarations(OutputList &ol,
     }
     else
     {
-      writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,inheritedFrom,inheritId);
+      writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,0,0,inheritId);
     }
 
     //printf("memberGroupList=%p\n",memberGroupList);
@@ -635,7 +635,7 @@ void MemberList::writeDeclarations(OutputList &ol,
         ol.startMemberGroup();
       }
       //printf("--- mg->writePlainDeclarations ---\n");
-      mg->writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,inheritedFrom,inheritId);
+      mg->writePlainDeclarations(ol,inGroup,cd,nd,fd,gd,0,inheritedFrom,inheritId);
       if (inheritId.isEmpty())
       {
         ol.endMemberGroup(hasHeader);
index 426739d..2f207c6 100644 (file)
@@ -97,7 +97,7 @@ class MemberList : public MemberVector
     int countInheritableMembers(const ClassDef *inheritedFrom) const;
     void writePlainDeclarations(OutputList &ol,bool inGroup,
                const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd, const GroupDef *gd,
-               const ClassDef *inheritedFrom,const QCString &inheritId) const;
+               int indentLevel,const ClassDef *inheritedFrom,const QCString &inheritId) const;
     void writeDeclarations(OutputList &ol,
                const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
                const QCString &title,const QCString &subtitle,
index a99ad21..ad8076d 100644 (file)
 
 #include <mutex>
 
-static QCString outputFormat;
-static const char *warning_str = "warning: ";
-static const char *error_str = "error: ";
-
-static FILE *warnFile = stderr;
-
-enum warn_as_error
-{
-   WARN_NO,
-   WARN_YES,
-   FAIL_ON_WARNINGS,
-};
-static warn_as_error warnBehavior = WARN_NO;
-static bool warnStat = false;
-
-static std::mutex g_mutex;
+// globals
+static QCString        g_warnFormat;
+static const char *    g_warningStr = "warning: ";
+static const char *    g_errorStr = "error: ";
+static FILE *          g_warnFile = stderr;
+static WARN_AS_ERROR_t g_warnBehavior = WARN_AS_ERROR_t::NO;
+static bool            g_warnStat = false;
+static std::mutex      g_mutex;
 
 void initWarningFormat()
 {
-  outputFormat = Config_getString(WARN_FORMAT);
+  g_warnFormat = Config_getString(WARN_FORMAT);
+  QCString logFile = Config_getString(WARN_LOGFILE);
 
-  if (!Config_getString(WARN_LOGFILE).isEmpty())
+  if (!logFile.isEmpty())
   {
-    warnFile = Portable::fopen(Config_getString(WARN_LOGFILE).data(),"w");
+    if (logFile == "-")
+    {
+      g_warnFile = stdout;
+    }
+    else if (!(g_warnFile = Portable::fopen(logFile,"w")))
+    {
+      // point it to something valid, because warn() relies on it
+      g_warnFile = stderr;
+      err("Cannot open '%s' for writing, redirecting 'WARN_LOGFILE' output to 'stderr'\n",logFile.data());
+    }
   }
-  if (!warnFile) // point it to something valid, because warn() relies on it
+  else
   {
-    warnFile = stderr;
+    g_warnFile = stderr;
   }
-
-  QCString warnStr = Config_getEnum(WARN_AS_ERROR).upper();
-  if (warnStr =="NO") warnBehavior=WARN_NO;
-  else if (warnStr =="YES") warnBehavior=WARN_YES;
-  else if (warnStr =="FAIL_ON_WARNINGS") warnBehavior=FAIL_ON_WARNINGS;
-  if (warnBehavior == WARN_YES)
+  g_warnBehavior = Config_getEnum(WARN_AS_ERROR);
+  if (g_warnBehavior != WARN_AS_ERROR_t::NO)
   {
-    warning_str = error_str;
+    g_warningStr = g_errorStr;
   }
 }
 
@@ -91,7 +89,7 @@ static void format_warn(const QCString &file,int line,const QCString &text)
         substitute(
           substitute(
             substitute(
-              outputFormat,
+              g_warnFormat,
               "$file",fileSubst
             ),
             "$line",lineSubst
@@ -100,7 +98,7 @@ static void format_warn(const QCString &file,int line,const QCString &text)
         ),
         "$text",textSubst
       );
-  if (warnBehavior == WARN_YES)
+  if (g_warnBehavior == WARN_AS_ERROR_t::YES)
   {
     msgText += " (warning treated as error, aborting now)";
   }
@@ -109,27 +107,27 @@ static void format_warn(const QCString &file,int line,const QCString &text)
   {
     std::unique_lock<std::mutex> lock(g_mutex);
     // print resulting message
-    fwrite(msgText.data(),1,msgText.length(),warnFile);
+    fwrite(msgText.data(),1,msgText.length(),g_warnFile);
   }
-  if (warnBehavior == WARN_YES)
+  if (g_warnBehavior == WARN_AS_ERROR_t::YES)
   {
     exit(1);
   }
-  warnStat = true;
+  g_warnStat = true;
 }
 
 static void handle_warn_as_error()
 {
-  if (warnBehavior == WARN_YES)
+  if (g_warnBehavior == WARN_AS_ERROR_t::YES)
   {
     {
       std::unique_lock<std::mutex> lock(g_mutex);
       QCString msgText = " (warning treated as error, aborting now)\n";
-      fwrite(msgText.data(),1,msgText.length(),warnFile);
+      fwrite(msgText.data(),1,msgText.length(),g_warnFile);
     }
     exit(1);
   }
-  warnStat = true;
+  g_warnStat = true;
 }
 
 static void do_warn(bool enabled, const QCString &file, int line, const char *prefix, const char *fmt, va_list args)
@@ -165,26 +163,26 @@ void warn(const QCString &file,int line,const char *fmt, ...)
 {
   va_list args;
   va_start(args, fmt);
-  do_warn(Config_getBool(WARNINGS), file, line, warning_str, fmt, args);
+  do_warn(Config_getBool(WARNINGS), file, line, g_warningStr, fmt, args);
   va_end(args);
 }
 
 void va_warn(const QCString &file,int line,const char *fmt,va_list args)
 {
-  do_warn(Config_getBool(WARNINGS), file, line, warning_str, fmt, args);
+  do_warn(Config_getBool(WARNINGS), file, line, g_warningStr, fmt, args);
 }
 
 void warn_simple(const QCString &file,int line,const char *text)
 {
   if (!Config_getBool(WARNINGS)) return; // warning type disabled
-  format_warn(file,line,QCString(warning_str) + text);
+  format_warn(file,line,QCString(g_warningStr) + text);
 }
 
 void warn_undoc(const QCString &file,int line,const char *fmt, ...)
 {
   va_list args;
   va_start(args, fmt);
-  do_warn(Config_getBool(WARN_IF_UNDOCUMENTED), file, line, warning_str, fmt, args);
+  do_warn(Config_getBool(WARN_IF_UNDOCUMENTED), file, line, g_warningStr, fmt, args);
   va_end(args);
 }
 
@@ -192,7 +190,7 @@ void warn_incomplete_doc(const QCString &file,int line,const char *fmt, ...)
 {
   va_list args;
   va_start(args, fmt);
-  do_warn(Config_getBool(WARN_IF_INCOMPLETE_DOC), file, line, warning_str, fmt, args);
+  do_warn(Config_getBool(WARN_IF_INCOMPLETE_DOC), file, line, g_warningStr, fmt, args);
   va_end(args);
 }
 
@@ -200,7 +198,7 @@ void warn_doc_error(const QCString &file,int line,const char *fmt, ...)
 {
   va_list args;
   va_start(args, fmt);
-  do_warn(Config_getBool(WARN_IF_DOC_ERROR), file, line, warning_str, fmt, args);
+  do_warn(Config_getBool(WARN_IF_DOC_ERROR), file, line, g_warningStr, fmt, args);
   va_end(args);
 }
 
@@ -208,7 +206,7 @@ void warn_uncond(const char *fmt, ...)
 {
   va_list args;
   va_start(args, fmt);
-  vfprintf(warnFile, (QCString(warning_str) + fmt).data(), args);
+  vfprintf(g_warnFile, (QCString(g_warningStr) + fmt).data(), args);
   va_end(args);
   handle_warn_as_error();
 }
@@ -217,7 +215,7 @@ void err(const char *fmt, ...)
 {
   va_list args;
   va_start(args, fmt);
-  vfprintf(warnFile, (QCString(error_str) + fmt).data(), args);
+  vfprintf(g_warnFile, (QCString(g_errorStr) + fmt).data(), args);
   va_end(args);
   handle_warn_as_error();
 }
@@ -226,7 +224,7 @@ extern void err_full(const QCString &file,int line,const char *fmt, ...)
 {
   va_list args;
   va_start(args, fmt);
-  do_warn(TRUE, file, line, error_str, fmt, args);
+  do_warn(TRUE, file, line, g_errorStr, fmt, args);
   va_end(args);
 }
 
@@ -236,12 +234,12 @@ void term(const char *fmt, ...)
     std::unique_lock<std::mutex> lock(g_mutex);
     va_list args;
     va_start(args, fmt);
-    vfprintf(warnFile, (QCString(error_str) + fmt).data(), args);
+    vfprintf(g_warnFile, (QCString(g_errorStr) + fmt).data(), args);
     va_end(args);
-    if (warnFile != stderr)
+    if (g_warnFile != stderr)
     {
-      for (int i = 0; i < (int)strlen(error_str); i++) fprintf(warnFile, " ");
-      fprintf(warnFile, "%s\n", "Exiting...");
+      for (int i = 0; i < (int)strlen(g_errorStr); i++) fprintf(g_warnFile, " ");
+      fprintf(g_warnFile, "%s\n", "Exiting...");
     }
   }
   exit(1);
@@ -249,7 +247,7 @@ void term(const char *fmt, ...)
 
 void warn_flush()
 {
-  fflush(warnFile);
+  fflush(g_warnFile);
 }
 
 
@@ -283,7 +281,7 @@ void printlex(int dbg, bool enter, const char *lexName, const char *fileName)
 
 extern void finishWarnExit()
 {
-  if (warnStat && warnBehavior == FAIL_ON_WARNINGS)
+  if (g_warnStat && g_warnBehavior == WARN_AS_ERROR_t::FAIL_ON_WARNINGS)
   {
     exit(1);
   }
index a9db9d8..fff8ad5 100644 (file)
@@ -73,7 +73,7 @@ static bool convertMapFile(TextStream &t,const QCString &mapName,const QCString
         std::unique_ptr<IDocParser> parser { createDocParser() };
         std::unique_ptr<DocRef>     df     { createRef( *parser.get(), url, context ) };
         t << externalRef(relPath,df->ref(),TRUE);
-        if (!df->file().isEmpty()) t << df->file() << Doxygen::htmlFileExtension;
+        if (!df->file().isEmpty()) t << addHtmlExtensionIfMissing(df->file());
         if (!df->anchor().isEmpty()) t << "#" << df->anchor();
       }
       else
index fec3275..f8539c0 100644 (file)
@@ -558,7 +558,7 @@ void NamespaceDefImpl::writeTagFile(TextStream &tagFile)
 {
   tagFile << "  <compound kind=\"namespace\">\n";
   tagFile << "    <name>" << convertToXML(name()) << "</name>\n";
-  tagFile << "    <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>\n";
+  tagFile << "    <filename>" << addHtmlExtensionIfMissing(getOutputFileBase()) << "</filename>\n";
   QCString idStr = id();
   if (!idStr.isEmpty())
   {
@@ -945,13 +945,12 @@ void NamespaceDefImpl::writeDocumentation(OutputList &ol)
   endTitle(ol,getOutputFileBase(),displayName());
   ol.startContents();
 
-  if (Doxygen::searchIndex)
-  {
-    Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
-    Doxygen::searchIndex->addWord(localName(),TRUE);
-  }
-
-  Doxygen::indexList->addIndexItem(this,0);
+  //if (Doxygen::searchIndex)
+  //{
+  //  Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
+  //  Doxygen::searchIndex->addWord(localName(),TRUE);
+  //}
+  //Doxygen::indexList->addIndexItem(this,0);
 
   //---------------------------------------- start flexible part -------------------------------
 
@@ -1138,7 +1137,7 @@ void NamespaceDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *cur
           ol.writeString("<a class=\"navtab\" ");
           ol.writeString("href=\"");
           if (createSubDirs) ol.writeString("../../");
-          ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor());
+          ol.writeString(addHtmlExtensionIfMissing(md->getOutputFileBase())+"#"+md->anchor());
           ol.writeString("\">");
           ol.writeString(convertToHtml(md->localName()));
           ol.writeString("</a>");
index d7f8f15..1f67a76 100644 (file)
@@ -96,9 +96,10 @@ class CodeOutputInterface
      *  \param file       The file part of the URL pointing to the docs.
      *  \param anchor     The anchor part of the URL pointing to the docs.
      *  \param lineNumber The line number to write
+     *  \param writeLineAnchor Indicates if an anchor for the line number needs to be written
      */
     virtual void writeLineNumber(const QCString &ref,const QCString &file,
-                                 const QCString &anchor,int lineNumber) = 0;
+                                 const QCString &anchor,int lineNumber, bool writeLineAnchor) = 0;
 
     /*! Writes a tool tip definition
      *  \param id       unique identifier for the tooltip
index d556375..3175a76 100644 (file)
@@ -174,7 +174,6 @@ void OutputList::writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *m
     //    ctx?qPrint(ctx->getDefFileExtension()):"<null>");
     if (og->isEnabled()) og->writeDoc(root,ctx,md,m_id);
   }
-  VhdlDocGen::setFlowMember(0);
 }
 
 void OutputList::parseText(const QCString &textStr)
index c7e0fd4..267a717 100644 (file)
@@ -247,8 +247,8 @@ class OutputList : public OutputDocInterface
     void endCodeLine()
     { forall(&OutputGenerator::endCodeLine); }
     void writeLineNumber(const QCString &ref,const QCString &file,const QCString &anchor,
-                         int lineNumber)
-    { forall(&OutputGenerator::writeLineNumber,ref,file,anchor,lineNumber); }
+                         int lineNumber, bool writeLineAnchor)
+    { forall(&OutputGenerator::writeLineNumber,ref,file,anchor,lineNumber,writeLineAnchor); }
     void startEmphasis()
     { forall(&OutputGenerator::startEmphasis); }
     void endEmphasis()
index 810591e..701b769 100644 (file)
@@ -162,7 +162,7 @@ void PageDefImpl::writeTagFile(TextStream &tagFile)
     tagFile << "  <compound kind=\"page\">\n";
     tagFile << "    <name>" << name() << "</name>\n";
     tagFile << "    <title>" << convertToXML(title()) << "</title>\n";
-    tagFile << "    <filename>" << convertToXML(getOutputFileBase())<< Doxygen::htmlFileExtension << "</filename>\n";
+    tagFile << "    <filename>" << addHtmlExtensionIfMissing(getOutputFileBase()) << "</filename>\n";
     writeDocAnchorsToTagFile(tagFile);
     tagFile << "  </compound>\n";
   }
@@ -287,14 +287,12 @@ void PageDefImpl::writeDocumentation(OutputList &ol)
 
   ol.popGeneratorState();
   //1.}
-
-  Doxygen::indexList->addIndexItem(this,0,QCString(),filterTitle(title().str()));
 }
 
 void PageDefImpl::writePageDocumentation(OutputList &ol) const
 {
   ol.startTextBlock();
-  QCString docStr = documentation()+inbodyDocumentation();
+  QCString docStr = (briefDescription().isEmpty()?"":briefDescription()+"\n\n")+documentation()+inbodyDocumentation();
   if (hasBriefDescription() && !SectionManager::instance().find(name()))
   {
     ol.pushGeneratorState();
index 002cc57..5503081 100644 (file)
@@ -649,9 +649,16 @@ void PerlModDocVisitor::visit(DocStyleChange *s)
     case DocStyleChange::Superscript:   style = "superscript"; break;
     case DocStyleChange::Center:        style = "center"; break;
     case DocStyleChange::Small:         style = "small"; break;
+    case DocStyleChange::Cite:          style = "cite"; break;
     case DocStyleChange::Preformatted:  style = "preformatted"; break;
     case DocStyleChange::Div:           style = "div"; break;
     case DocStyleChange::Span:          style = "span"; break;
+    case DocStyleChange::Details: /* emulation of the <details> tag */
+      style = "details";
+      break;
+    case DocStyleChange::Summary: /* emulation of the <summary> tag inside a <details> tag */
+      style = "summary";
+      break;
 
   }
   openItem("style");
@@ -672,6 +679,8 @@ void PerlModDocVisitor::visit(DocVerbatim *s)
       m_output.add("</programlisting>");
       return;
 #endif
+    case DocVerbatim::JavaDocCode:
+    case DocVerbatim::JavaDocLiteral:
     case DocVerbatim::Verbatim:  type = "preformatted"; break;
     case DocVerbatim::HtmlOnly:  type = "htmlonly";     break;
     case DocVerbatim::RtfOnly:   type = "rtfonly";      break;
@@ -950,7 +959,17 @@ void PerlModDocVisitor::visitPost(DocHtmlList *)
   closeItem();
 }
 
-void PerlModDocVisitor::visitPre(DocHtmlListItem *) { openSubBlock(); }
+void PerlModDocVisitor::visitPre(DocHtmlListItem *l)
+{
+  for (const auto &opt : l->attribs())
+  {
+    if (opt.name=="value")
+    {
+      m_output.addFieldQuotedString("item_value", qPrint(opt.value));
+    }
+  }
+  openSubBlock();
+}
 void PerlModDocVisitor::visitPost(DocHtmlListItem *) { closeSubBlock(); }
 
 //void PerlModDocVisitor::visitPre(DocHtmlPre *)
index 2e7f04e..fed8b67 100644 (file)
@@ -90,10 +90,6 @@ QCString PlantumlManager::writePlantUMLSource(const QCString &outDirArg,const QC
 
 void PlantumlManager::generatePlantUMLOutput(const QCString &baseName,const QCString &outDir,OutputFormat format)
 {
-  QCString plantumlJarPath = Config_getString(PLANTUML_JAR_PATH);
-  QCString plantumlConfigFile = Config_getString(PLANTUML_CFG_FILE);
-  QCString dotPath = Config_getString(DOT_PATH);
-
   QCString imgName = baseName;
   // The basename contains path, we need to strip the path from the filename in order
   // to create the image file name which should be included in the index.qhp (Qt help index file).
@@ -171,7 +167,7 @@ static void runPlantumlContent(const PlantumlManager::FilesMap &plantumlFiles,
     }
   }
   if (!pumlIncludePathList.empty()) pumlArgs += "\" ";
-  pumlArgs += "-Djava.awt.headless=true -jar \""+plantumlJarPath+"plantuml.jar\" ";
+  pumlArgs += "-Djava.awt.headless=true -jar \""+plantumlJarPath+"\" ";
   if (!plantumlConfigFile.isEmpty())
   {
     pumlArgs += "-config \"";
@@ -249,7 +245,7 @@ static void runPlantumlContent(const PlantumlManager::FilesMap &plantumlFiles,
       Portable::sysTimerStart();
       if ((exitCode=Portable::system(pumlExe.data(),pumlArguments.data(),TRUE))!=0)
       {
-        err_full(nb.srcFile,nb.srcLine,"Problems running PlantUML. Verify that the command 'java -jar \"%splantuml.jar\" -h' works from the command line. Exit code: %d\n",
+        err_full(nb.srcFile,nb.srcLine,"Problems running PlantUML. Verify that the command 'java -jar \"%s\" -h' works from the command line. Exit code: %d\n",
             plantumlJarPath.data(),exitCode);
       }
       Portable::sysTimerStop();
index 5c26a76..abe1359 100644 (file)
--- a/src/pre.l
+++ b/src/pre.l
 %option extra-type="struct preYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -73,9 +77,9 @@
 static const char *stateToString(int state);
 #endif
 
-struct CondCtx
+struct preYY_CondCtx
 {
-  CondCtx(int line,QCString id,bool b)
+  preYY_CondCtx(int line,QCString id,bool b)
     : lineNr(line),sectionId(id), skip(b) {}
   int lineNr;
   QCString sectionId;
@@ -249,7 +253,7 @@ struct preYY_state
   int                yyLineNr       = 1;
   int                yyMLines       = 1;
   int                yyColNr        = 1;
-  QCString           yyFileName;
+  QCString           fileName;
   FileDef           *yyFileDef      = 0;
   FileDef           *inputFileDef   = 0;
   int                ifcount        = 0;
@@ -268,6 +272,7 @@ struct preYY_state
   BufStr            *outputBuf      = 0;
   int                roundCount     = 0;
   bool               quoteArg       = false;
+  bool               idStart        = false;
   int                findDefArgContext = 0;
   bool               expectGuard    = false;
   QCString           guardName;
@@ -276,6 +281,7 @@ struct preYY_state
   QCString           guardExpr;
   int                curlyCount     = 0;
   bool               nospaces       = false; // add extra spaces during macro expansion
+  int                javaBlock      = 0;
 
   bool               macroExpansion = false; // from the configuration
   bool               expandOnlyPredef = false; // from the configuration
@@ -297,7 +303,7 @@ struct preYY_state
   StringVector                             pathList;
   IntMap                                   argMap;
   BoolStack                                levelGuard;
-  std::stack< std::unique_ptr<CondCtx> >   condStack;
+  std::stack< std::unique_ptr<preYY_CondCtx> >   condStack;
   std::deque< std::unique_ptr<FileState> > includeStack;
   std::unordered_map<std::string,Define*>  expandedDict;
   StringUnorderedSet                       expanded;
@@ -340,6 +346,10 @@ static Define *       isDefined(yyscan_t yyscanner,const QCString &name);
 #undef  YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
+
 /* ----------------------------------------------------------------- */
 
 %}
@@ -385,13 +395,12 @@ WSopt [ \t\r]*
 %x      DefineArg
 %x      DefineText
 %x      SkipCPPBlock
-%x      Ifdef
-%x      Ifndef
 %x      SkipCComment
 %x      ArgCopyCComment
 %x      CopyCComment
 %x      SkipVerbatim
 %x      SkipCPPComment
+%x      JavaDocVerbatimCode
 %x      RemoveCComment
 %x      RemoveCPPComment
 %x      Guard
@@ -422,7 +431,7 @@ WSopt [ \t\r]*
                                           BEGIN(Command); 
                                         }
 <Start>^("%top{"|"%{")                  {
-                                          if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Lex) REJECT
+                                          if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt_Lex) REJECT
                                           outputArray(yyscanner,yytext,yyleng);
                                           BEGIN(LexCopyLine);
                                         }
@@ -471,7 +480,7 @@ WSopt [ \t\r]*
                                             BEGIN(CopyLine);
                                           }
                                         }
-<CopyLine,LexCopyLine>"extern"{BN}{0,80}"\"C\""*{BN}{0,80}"{"   {
+<CopyLine,LexCopyLine>"extern"{BN}*"\""[^\"]+"\""{BN}*("{")?  {
                                           QCString text=yytext;
                                           yyextra->yyLineNr+=text.contains('\n');
                                           outputArray(yyscanner,yytext,yyleng);
@@ -509,13 +518,13 @@ WSopt [ \t\r]*
                                           outputArray(yyscanner,yytext,yyleng);
                                         }
 <CopyLine,LexCopyLine>@\"               {
-                                          if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_CSharp) REJECT;
+                                          if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt_CSharp) REJECT;
                                           outputArray(yyscanner,yytext,yyleng);
                                           BEGIN( CopyStringCs );
                                         }
 <CopyLine,LexCopyLine>\"                {
                                           outputChar(yyscanner,*yytext);
-                                          if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Fortran)
+                                          if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt_Fortran)
                                           {
                                             BEGIN( CopyString );
                                           }
@@ -525,7 +534,7 @@ WSopt [ \t\r]*
                                           }
                                         }
 <CopyLine,LexCopyLine>\'                {
-                                          if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Fortran) REJECT;
+                                          if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt_Fortran) REJECT;
                                           outputChar(yyscanner,*yytext);
                                           BEGIN( CopyStringFtn );
                                         }
@@ -633,7 +642,7 @@ WSopt [ \t\r]*
                                           }
                                         }
 <CopyLine,LexCopyLine>"\\"\r?/\n        { // strip line continuation characters
-                                          if (getLanguageFromFileName(yyextra->yyFileName)==SrcLangExt_Fortran) outputChar(yyscanner,*yytext);
+                                          if (getLanguageFromFileName(yyextra->fileName)==SrcLangExt_Fortran) outputChar(yyscanner,*yytext);
                                         }
 <CopyLine,LexCopyLine>\\.               {
                                           outputArray(yyscanner,yytext,(int)yyleng);
@@ -688,7 +697,7 @@ WSopt [ \t\r]*
                                           BEGIN(ReadString);
                                         }
 <FindDefineArgs>'                       {
-                                          if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Fortran) REJECT;
+                                          if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt_Fortran) REJECT;
                                           yyextra->defArgsStr+=*yytext;
                                           BEGIN(ReadString);
                                         }
@@ -723,7 +732,7 @@ WSopt [ \t\r]*
                                           BEGIN(FindDefineArgs);
                                         }
 <ReadString>"'"                         {
-                                          if (getLanguageFromFileName(yyextra->yyFileName)!=SrcLangExt_Fortran) REJECT;
+                                          if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt_Fortran) REJECT;
                                           yyextra->defArgsStr+=*yytext;
                                           BEGIN(FindDefineArgs);
                                         }
@@ -862,6 +871,16 @@ WSopt [ \t\r]*
 <Guard>"defined"/{B}+                   {
                                           BEGIN(DefinedExpr1);
                                         }
+<Guard>"true"/{B}|{B}*[\r]?\n           { yyextra->guardExpr+="1L"; }
+<Guard>"false"/{B}|{B}*[\r]?\n          { yyextra->guardExpr+="0L"; }
+<Guard>"not"/{B}                        { yyextra->guardExpr+='!'; }
+<Guard>"not_eq"/{B}                     { yyextra->guardExpr+="!="; }
+<Guard>"and"/{B}                        { yyextra->guardExpr+="&&"; }
+<Guard>"or"/{B}                         { yyextra->guardExpr+="||"; }
+<Guard>"bitand"/{B}                     { yyextra->guardExpr+="&"; }
+<Guard>"bitor"/{B}                      { yyextra->guardExpr+="|"; }
+<Guard>"xor"/{B}                        { yyextra->guardExpr+="^"; }
+<Guard>"compl"/{B}                      { yyextra->guardExpr+="~"; }
 <Guard>{ID}                             { yyextra->guardExpr+=yytext; }
 <Guard>"@"                              { yyextra->guardExpr+="@@"; }
 <Guard>.                                { yyextra->guardExpr+=*yytext; }
@@ -1223,11 +1242,11 @@ WSopt [ \t\r]*
                                             BEGIN(SkipVerbatim);
                                           }
                                         }
-<SkipCComment>[\\@][\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly"|"dot"|"code"("{"[^}]*"}")?){BN}+ {
+<SkipCComment>[\\@][\\@]("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly"|"dot"|"code"("{"[^}]*"}")?){BN}+ {
                                           outputArray(yyscanner,yytext,yyleng);
                                           yyextra->yyLineNr+=QCString(yytext).contains('\n');
                                         }
-<SkipCComment>[\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly"|"dot"|"code"("{"[^}]*"}")?){BN}+      {
+<SkipCComment>[\\@]("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"rtfonly"|"manonly"|"dot"|"code"("{"[^}]*"}")?){BN}+      {
                                           outputArray(yyscanner,yytext,yyleng);
                                           yyextra->yyLineNr+=QCString(yytext).contains('\n');
                                           yyextra->fenceSize=0;
@@ -1244,6 +1263,21 @@ WSopt [ \t\r]*
                                           }
                                           BEGIN(SkipVerbatim);
                                         }
+<SkipCond>[\\@][\\@]"cond"[ \t]+        {}// escaped cond command
+<SkipCond>[\\@]"cond"[ \t]+             { // cond command in a skipped cond section, this section has to be skipped as well
+                                          // but has to be recorded to match the endcond command
+                                          startCondSection(yyscanner," ");
+                                        }
+<SkipCComment>"{"[ \t]*"@code"/[ \t\n]  {
+                                          outputArray(yyscanner,"@iliteral{code}",15);
+                                          yyextra->javaBlock=1;
+                                          BEGIN(JavaDocVerbatimCode);
+                                        }
+<SkipCComment>"{"[ \t]*"@literal"/[ \t\n]  {
+                                          outputArray(yyscanner,"@iliteral",9);
+                                          yyextra->javaBlock=1;
+                                          BEGIN(JavaDocVerbatimCode);
+                                        }
 <SkipCComment,SkipCPPComment>[\\@][\\@]"cond"[ \t]+ { // escaped @cond
                                           outputArray(yyscanner,yytext,yyleng);
                                         }
@@ -1346,7 +1380,7 @@ WSopt [ \t\r]*
                                             BEGIN(yyextra->condCtx);
                                           }
                                         }
-<SkipVerbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"f$"|"f]"|"f}""f}") { /* end of verbatim block */
+<SkipVerbatim>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"f$"|"f]"|"f}""f}") { /* end of verbatim block */
                                           outputArray(yyscanner,yytext,yyleng);
                                           if (yytext[1]=='f' && yyextra->blockName=="f")
                                           {
@@ -1374,7 +1408,43 @@ WSopt [ \t\r]*
 <SkipVerbatim>{CCE}|{CCS}                       {
                                           outputArray(yyscanner,yytext,yyleng);
                                         }
-<SkipCComment,SkipVerbatim>[^*\\@\x06~`\n\/]+ {
+<JavaDocVerbatimCode>"{"                {
+                                          if (yyextra->javaBlock==0)
+                                          {
+                                            REJECT;
+                                          }
+                                          else
+                                          {
+                                            yyextra->javaBlock++;
+                                            outputArray(yyscanner,yytext,(int)yyleng);
+                                          }
+                                        }
+<JavaDocVerbatimCode>"}"                {
+                                          if (yyextra->javaBlock==0)
+                                          {
+                                            REJECT;
+                                          }
+                                          else
+                                          {
+                                            yyextra->javaBlock--;
+                                            if (yyextra->javaBlock==0)
+                                            {
+                                              outputArray(yyscanner," @endiliteral ",14);
+                                              BEGIN(SkipCComment);
+                                            }
+                                            else
+                                            {
+                                              outputArray(yyscanner,yytext,(int)yyleng);
+                                            }
+                                          }
+                                        }
+<JavaDocVerbatimCode>\n                 { /* new line in verbatim block */
+                                          outputArray(yyscanner,yytext,(int)yyleng);
+                                        }
+<JavaDocVerbatimCode>.                  { /* any other character */
+                                          outputArray(yyscanner,yytext,(int)yyleng);
+                                        }
+<SkipCComment,SkipVerbatim>[^{*\\@\x06~`\n\/]+ {
                                           outputArray(yyscanner,yytext,yyleng);
                                         }
 <SkipCComment,SkipVerbatim>\n           {
@@ -1446,6 +1516,7 @@ WSopt [ \t\r]*
 <DefineText>"#"/{IDSTART}               {
                                           outputChar(yyscanner,' ');
                                           yyextra->quoteArg=TRUE;
+                                          yyextra->idStart=true;
                                           yyextra->defLitText+=yytext;
                                         }
 <DefineText,CopyCComment>{ID}           {
@@ -1466,6 +1537,12 @@ WSopt [ \t\r]*
                                             }
                                             else
                                             {
+                                              if (yyextra->idStart)
+                                              {
+                                                warn(yyextra->fileName,yyextra->yyLineNr,
+                                                  "'#' is not followed by a macro parameter '%s': '%s'",
+                                                  qPrint(yyextra->defName),qPrint(yyextra->defLitText.stripWhiteSpace()));
+                                              }
                                               yyextra->defText+=yytext;
                                             }
                                           }
@@ -1478,6 +1555,7 @@ WSopt [ \t\r]*
                                             yyextra->defText+="\"";
                                           }
                                           yyextra->quoteArg=FALSE;
+                                          yyextra->idStart=false;
                                         }
 <CopyCComment>.                         {
                                           yyextra->defLitText+=yytext;
@@ -1495,19 +1573,19 @@ WSopt [ \t\r]*
                                           yyextra->defText = yyextra->defText.stripWhiteSpace();
                                           if (yyextra->defText.startsWith("##"))
                                           {
-                                            warn(yyextra->yyFileName,yyextra->yyLineNr,
+                                            warn(yyextra->fileName,yyextra->yyLineNr,
                                                  "'##' cannot occur at the beginning of a macro definition '%s': '%s'",
                                                  qPrint(yyextra->defName),qPrint(yyextra->defLitText.stripWhiteSpace()));
                                           }
                                           else if (yyextra->defText.endsWith("##"))
                                           {
-                                            warn(yyextra->yyFileName,yyextra->yyLineNr,
+                                            warn(yyextra->fileName,yyextra->yyLineNr,
                                                  "'##' cannot occur at the end of a macro definition '%s': '%s'",
                                                  qPrint(yyextra->defName),qPrint(yyextra->defLitText.stripWhiteSpace()));
                                           }
                                           else if (yyextra->defText.endsWith("#"))
                                           {
-                                            warn(yyextra->yyFileName,yyextra->yyLineNr,
+                                            warn(yyextra->fileName,yyextra->yyLineNr,
                                                  "expected formal parameter after # in macro definition '%s': '%s'",
                                                  qPrint(yyextra->defName),qPrint(yyextra->defLitText.stripWhiteSpace()));
                                           }
@@ -1541,7 +1619,7 @@ WSopt [ \t\r]*
                                               def->name = yyextra->defName;
                                               def->definition = yyextra->defText.stripWhiteSpace();
                                               def->nargs = yyextra->defArgs;
-                                              def->fileName = yyextra->yyFileName;
+                                              def->fileName = yyextra->fileName;
                                               def->lineNr = yyextra->yyLineNr-yyextra->yyMLines;
                                               def->columnNr = yyextra->yyColNr;
                                             }
@@ -1629,9 +1707,9 @@ WSopt [ \t\r]*
                                           }
                                           else
                                           {
-                                            QCString toFileName = yyextra->yyFileName;
+                                            QCString toFileName = yyextra->fileName;
                                             const std::unique_ptr<FileState> &fs=yyextra->includeStack.back();
-                                            //fileDefineCache->merge(yyextra->yyFileName,fs->fileName);
+                                            //fileDefineCache->merge(yyextra->fileName,fs->fileName);
                                             YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER;
                                             yy_switch_to_buffer( fs->bufState, yyscanner );
                                             yy_delete_buffer( oldBuf, yyscanner );
@@ -1641,12 +1719,12 @@ WSopt [ \t\r]*
                                             yyextra->inputBufPos = fs->oldFileBufPos;
                                             yyextra->curlyCount  = fs->curlyCount;
                                             setFileName(yyscanner,fs->fileName);
-                                            DBG_CTX((stderr,"######## FileName %s\n",qPrint(yyextra->yyFileName)));
+                                            DBG_CTX((stderr,"######## FileName %s\n",qPrint(yyextra->fileName)));
 
                                             // Deal with file changes due to
                                             // #include's within { .. } blocks
-                                            QCString lineStr(15+yyextra->yyFileName.length());
-                                            lineStr.sprintf("# %d \"%s\" 2",yyextra->yyLineNr,qPrint(yyextra->yyFileName));
+                                            QCString lineStr(15+yyextra->fileName.length());
+                                            lineStr.sprintf("# %d \"%s\" 2",yyextra->yyLineNr,qPrint(yyextra->fileName));
                                             outputString(yyscanner,lineStr);
 
                                             yyextra->includeStack.pop_back();
@@ -1660,7 +1738,7 @@ WSopt [ \t\r]*
                                               if (!g_defineManager.alreadyProcessed(toFileName.str()))
                                               {
                                                 // now that the file is completely processed, prevent it from processing it again
-                                                g_defineManager.addInclude(yyextra->yyFileName.str(),toFileName.str());
+                                                g_defineManager.addInclude(yyextra->fileName.str(),toFileName.str());
                                                 g_defineManager.store(toFileName.str(),yyextra->localDefines);
                                               }
                                               else
@@ -1708,7 +1786,7 @@ WSopt [ \t\r]*
                                           }
                                         }
 <*>{CPPC}[/!]?                          {
-                                          if (YY_START==SkipVerbatim || YY_START==SkipCond || getLanguageFromFileName(yyextra->yyFileName)==SrcLangExt_Fortran)
+                                          if (YY_START==SkipVerbatim || YY_START==SkipCond || getLanguageFromFileName(yyextra->fileName)==SrcLangExt_Fortran)
                                           {
                                             REJECT;
                                           }
@@ -1756,39 +1834,39 @@ static void setFileName(yyscan_t yyscanner,const QCString &name)
   YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
   bool ambig;
   FileInfo fi(name.str());
-  state->yyFileName=fi.absFilePath();
-  state->yyFileDef=findFileDef(Doxygen::inputNameLinkedMap,state->yyFileName,ambig);
+  state->fileName=fi.absFilePath();
+  state->yyFileDef=findFileDef(Doxygen::inputNameLinkedMap,state->fileName,ambig);
   if (state->yyFileDef==0) // if this is not an input file check if it is an
                       // include file
   {
-    state->yyFileDef=findFileDef(Doxygen::includeNameLinkedMap,state->yyFileName,ambig);
+    state->yyFileDef=findFileDef(Doxygen::includeNameLinkedMap,state->fileName,ambig);
   }
-  //printf("setFileName(%s) state->yyFileName=%s state->yyFileDef=%p\n",
-  //    name,qPrint(state->yyFileName),state->yyFileDef);
+  //printf("setFileName(%s) state->fileName=%s state->yyFileDef=%p\n",
+  //    name,qPrint(state->fileName),state->yyFileDef);
   if (state->yyFileDef && state->yyFileDef->isReference()) state->yyFileDef=0;
-  state->insideCS = getLanguageFromFileName(state->yyFileName)==SrcLangExt_CSharp;
-  state->insideFtn = getLanguageFromFileName(state->yyFileName)==SrcLangExt_Fortran;
-  state->isSource = guessSection(state->yyFileName);
+  state->insideCS = getLanguageFromFileName(state->fileName)==SrcLangExt_CSharp;
+  state->insideFtn = getLanguageFromFileName(state->fileName)==SrcLangExt_Fortran;
+  state->isSource = guessSection(state->fileName);
 }
 
 static void incrLevel(yyscan_t yyscanner)
 {
   YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
   state->levelGuard.push(false);
-  //printf("%s line %d: incrLevel %d\n",qPrint(yyextra->yyFileName),yyextra->yyLineNr,yyextra->levelGuard.size());
+  //printf("%s line %d: incrLevel %d\n",qPrint(yyextra->fileName),yyextra->yyLineNr,yyextra->levelGuard.size());
 }
 
 static void decrLevel(yyscan_t yyscanner)
 {
   YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
-  //printf("%s line %d: decrLevel %d\n",qPrint(state->yyFileName),state->yyLineNr,state->levelGuard.size());
+  //printf("%s line %d: decrLevel %d\n",qPrint(state->fileName),state->yyLineNr,state->levelGuard.size());
   if (!state->levelGuard.empty())
   {
     state->levelGuard.pop();
   }
   else
   {
-    warn(state->yyFileName,state->yyLineNr,"More #endif's than #if's found.\n");
+    warn(state->fileName,state->yyLineNr,"More #endif's than #if's found.\n");
   }
 }
 
@@ -1797,7 +1875,7 @@ static bool otherCaseDone(yyscan_t yyscanner)
   YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
   if (state->levelGuard.empty())
   {
-    warn(state->yyFileName,state->yyLineNr,"Found an #else without a preceding #if.\n");
+    warn(state->fileName,state->yyLineNr,"Found an #else without a preceding #if.\n");
     return TRUE;
   }
   else
@@ -1873,7 +1951,7 @@ static FileState *checkAndOpenFile(yyscan_t yyscanner,const QCString &fileName,b
 static FileState *findFile(yyscan_t yyscanner, const QCString &fileName,bool localInclude,bool &alreadyProcessed)
 {
   YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
-  //printf("** findFile(%s,%d) state->yyFileName=%s\n",qPrint(fileName),localInclude,qPrint(state->yyFileName));
+  //printf("** findFile(%s,%d) state->fileName=%s\n",qPrint(fileName),localInclude,qPrint(state->fileName));
   if (Portable::isAbsolutePath(fileName))
   {
     FileState *fs = checkAndOpenFile(yyscanner,fileName,alreadyProcessed);
@@ -1888,9 +1966,9 @@ static FileState *findFile(yyscan_t yyscanner, const QCString &fileName,bool loc
       return 0;
     }
   }
-  if (localInclude && !state->yyFileName.isEmpty())
+  if (localInclude && !state->fileName.isEmpty())
   {
-    FileInfo fi(state->yyFileName.str());
+    FileInfo fi(state->fileName.str());
     if (fi.exists())
     {
       QCString absName = QCString(fi.dirPath(TRUE))+"/"+fileName;
@@ -2823,7 +2901,7 @@ static bool computeExpression(yyscan_t yyscanner,const QCString &expr)
   e = removeIdsAndMarkers(e);
   if (e.isEmpty()) return FALSE;
   //printf("parsing '%s'\n",qPrint(e));
-  return state->constExpParser.parse(state->yyFileName.data(),state->yyLineNr,e.str());
+  return state->constExpParser.parse(state->fileName.data(),state->yyLineNr,e.str());
 }
 
 /*! expands the macro definition in \a name
@@ -2848,7 +2926,7 @@ static void addDefine(yyscan_t yyscanner)
   def.name       = state->defName;
   def.definition = state->defText.stripWhiteSpace();
   def.nargs      = state->defArgs;
-  def.fileName   = state->yyFileName;
+  def.fileName   = state->fileName;
   def.fileDef    = state->yyFileDef;
   def.lineNr     = state->yyLineNr-state->yyMLines;
   def.columnNr   = state->yyColNr;
@@ -2876,7 +2954,7 @@ static void addMacroDefinition(yyscan_t yyscanner)
                       // conditional section (cond command) that is disabled.
 
   Define define;
-  define.fileName = state->yyFileName;
+  define.fileName = state->fileName;
   define.lineNr   = state->yyLineNr - state->yyMLines;
   define.columnNr = state->yyColNr;
   define.name     = state->defName;
@@ -3028,12 +3106,12 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc)
       return;
     }
 
-    QCString oldFileName = state->yyFileName;
+    QCString oldFileName = state->fileName;
     FileDef *oldFileDef  = state->yyFileDef;
     int oldLineNr        = state->yyLineNr;
     //printf("Searching for '%s'\n",qPrint(incFileName));
 
-    QCString absIncFileName = determineAbsoluteIncludeName(state->yyFileName,incFileName);
+    QCString absIncFileName = determineAbsoluteIncludeName(state->fileName,incFileName);
 
     // findFile will overwrite state->yyFileDef if found
     FileState *fs;
@@ -3086,8 +3164,8 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc)
 
       // Deal with file changes due to
       // #include's within { .. } blocks
-      QCString lineStr(state->yyFileName.length()+20);
-      lineStr.sprintf("# 1 \"%s\" 1\n",qPrint(state->yyFileName));
+      QCString lineStr(state->fileName.length()+20);
+      lineStr.sprintf("# 1 \"%s\" 1\n",qPrint(state->fileName));
       outputString(yyscanner,lineStr);
 
       DBG_CTX((stderr,"Switching to include file %s\n",qPrint(incFileName)));
@@ -3102,7 +3180,7 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc)
                            // in the local context
       {
         std::lock_guard<std::mutex> lock(g_globalDefineMutex);
-        g_defineManager.addInclude(state->yyFileName.str(),absIncFileName.str());
+        g_defineManager.addInclude(state->fileName.str(),absIncFileName.str());
         g_defineManager.retrieve(absIncFileName.str(),state->contextDefines);
       }
 
@@ -3141,7 +3219,7 @@ static void readIncludeFile(yyscan_t yyscanner,const QCString &inc)
       }
       if (state->curlyCount>0 && !alreadyProcessed) // failed to find #include inside { ... }
       {
-        warn(state->yyFileName,state->yyLineNr,"include file %s not found, perhaps you forgot to add its directory to INCLUDE_PATH?",qPrint(incFileName));
+        warn(state->fileName,state->yyLineNr,"include file %s not found, perhaps you forgot to add its directory to INCLUDE_PATH?",qPrint(incFileName));
       }
     }
   }
@@ -3154,8 +3232,8 @@ static void startCondSection(yyscan_t yyscanner,const QCString &sectId)
   YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
   //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.size());
   CondParser prs;
-  bool expResult = prs.parse(state->yyFileName.data(),state->yyLineNr,sectId.data());
-  state->condStack.emplace(std::make_unique<CondCtx>(state->yyLineNr,sectId,state->skip));
+  bool expResult = prs.parse(state->fileName.data(),state->yyLineNr,sectId.data());
+  state->condStack.emplace(std::make_unique<preYY_CondCtx>(state->yyLineNr,sectId,state->skip));
   if (!expResult)
   {
     state->skip=TRUE;
@@ -3168,11 +3246,12 @@ static void endCondSection(yyscan_t yyscanner)
   YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
   if (state->condStack.empty())
   {
+    warn(state->fileName,state->yyLineNr,"the \\endcond does not have a corresponding \\cond in this file");
     state->skip=FALSE;
   }
   else
   {
-    const std::unique_ptr<CondCtx> &ctx = state->condStack.top();
+    const std::unique_ptr<preYY_CondCtx> &ctx = state->condStack.top();
     state->skip=ctx->skip;
     state->condStack.pop();
   }
@@ -3500,7 +3579,7 @@ void Preprocessor::processFile(const QCString &fileName,BufStr &input,BufStr &ou
   setFileName(yyscanner,fileName);
 
   state->inputFileDef = state->yyFileDef;
-  //yyextra->defineManager.startContext(state->yyFileName);
+  //yyextra->defineManager.startContext(state->fileName);
 
   initPredefined(yyscanner,fileName);
 
@@ -3519,7 +3598,7 @@ void Preprocessor::processFile(const QCString &fileName,BufStr &input,BufStr &ou
 
   while (!state->condStack.empty())
   {
-    const std::unique_ptr<CondCtx> &ctx = state->condStack.top();
+    const std::unique_ptr<preYY_CondCtx> &ctx = state->condStack.top();
     QCString sectionInfo = " ";
     if (ctx->sectionId!=" ") sectionInfo.sprintf(" with label '%s' ",qPrint(ctx->sectionId.stripWhiteSpace()));
     warn(fileName,ctx->lineNr,"Conditional section%sdoes not have "
@@ -3579,7 +3658,7 @@ void Preprocessor::processFile(const QCString &fileName,BufStr &input,BufStr &ou
       }
     }
     // add the macro definition for this file to the global map
-    Doxygen::macroDefinitions.emplace(std::make_pair(state->yyFileName.str(),std::move(state->macroDefinitions)));
+    Doxygen::macroDefinitions.emplace(std::make_pair(state->fileName.str(),std::move(state->macroDefinitions)));
   }
 
   //yyextra->defineManager.endContext();
index 3cdace8..1424e63 100644 (file)
@@ -137,6 +137,9 @@ class PrintDocVisitor : public DocVisitor
         case DocStyleChange::Small:
           if (s->enable()) printf("<small>"); else printf("</small>");
           break;
+        case DocStyleChange::Cite:
+          if (s->enable()) printf("<cite>"); else printf("</cite>");
+          break;
         case DocStyleChange::Preformatted:
           if (s->enable()) printf("<pre>"); else printf("</pre>");
           break;
@@ -146,6 +149,30 @@ class PrintDocVisitor : public DocVisitor
         case DocStyleChange::Span:
           if (s->enable()) printf("<span>"); else printf("</span>");
           break;
+        case DocStyleChange::Details:
+          if (s->enable())
+          {
+            indent_pre();
+            printf("<details>\n"); 
+          }
+          else 
+          {
+            indent_post();
+            printf("</details>\n");
+          }
+          break;
+        case DocStyleChange::Summary:
+          if (s->enable())
+          {
+            indent_pre();
+            printf("<summary>\n"); 
+          }
+          else 
+          {
+            indent_post();
+            printf("</summary>\n");
+          }
+          break;
       }
     }
     void visit(DocVerbatim *s)
@@ -155,6 +182,8 @@ class PrintDocVisitor : public DocVisitor
       {
         case DocVerbatim::Code: printf("<code>"); break;
         case DocVerbatim::Verbatim: printf("<verbatim>"); break;
+        case DocVerbatim::JavaDocLiteral: printf("<javadocliteral>"); break;
+        case DocVerbatim::JavaDocCode: printf("<javadoccode>"); break;
         case DocVerbatim::HtmlOnly: printf("<htmlonly>"); break;
         case DocVerbatim::RtfOnly: printf("<rtfonly>"); break;
         case DocVerbatim::ManOnly: printf("<manonly>"); break;
@@ -170,6 +199,8 @@ class PrintDocVisitor : public DocVisitor
       {
         case DocVerbatim::Code: printf("</code>"); break;
         case DocVerbatim::Verbatim: printf("</verbatim>"); break;
+        case DocVerbatim::JavaDocLiteral: printf("</javadocliteral>"); break;
+        case DocVerbatim::JavaDocCode: printf("</javadoccode>"); break;
         case DocVerbatim::HtmlOnly: printf("</htmlonly>"); break;
         case DocVerbatim::RtfOnly: printf("</rtfonly>"); break;
         case DocVerbatim::ManOnly: printf("</manonly>"); break;
@@ -402,10 +433,15 @@ class PrintDocVisitor : public DocVisitor
       indent_post();
       if (s->type()==DocHtmlList::Ordered) printf("</ol>\n"); else printf("</ul>\n");
     }
-    void visitPre(DocHtmlListItem *)
+    void visitPre(DocHtmlListItem *s)
     {
       indent_pre();
-      printf("<li>\n");
+      printf("<li");
+      for (const auto &opt : s->attribs())
+      {
+        printf(" %s=\"%s\"",qPrint(opt.name),qPrint(opt.value));
+      }
+      printf(">\n");
     }
     void visitPost(DocHtmlListItem *)
     {
@@ -535,6 +571,7 @@ class PrintDocVisitor : public DocVisitor
         case DocImage::Latex:   printf("latex"); break;
         case DocImage::Rtf:     printf("rtf"); break;
         case DocImage::DocBook: printf("docbook"); break;
+        case DocImage::Xml:     printf("xml"); break;
       }
       printf("\" %s %s inline=\"%s\">\n",qPrint(img->width()),qPrint(img->height()),img->isInlineImage() ? "yes" : "no");
     }
index b5fecd3..8756325 100644 (file)
 %option noyy_top_state
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -74,8 +78,9 @@ struct pycodeYY_state
   CodeOutputInterface * code = 0;
   const char *  inputString = 0;     //!< the code fragment as text
   yy_size_t     inputPosition = 0;   //!< read offset during parsing
+  QCString      fileName;
   const char *  currentFontClass = 0;
-  bool          needsTermination = FALSE;
+  bool          insideCodeLine = FALSE;
   const Definition *searchCtx = 0;
   bool          collectXRefs = FALSE;
   int           inputLines = 0;      //!< number of line in the code fragment
@@ -90,6 +95,7 @@ struct pycodeYY_state
   QCString      classScope;
   int           paramParens = 0;
 
+  bool          insideBody = false;
   bool          exampleBlock = FALSE;
   QCString      exampleName;
 
@@ -158,6 +164,10 @@ static std::mutex g_countFlowKeywordsMutex;
 #undef YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
+
 %}
 
 
@@ -285,9 +295,6 @@ TARGET            ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU
 %x SuiteCaptureIndent
 %x SuiteStart
 %x SuiteMaintain
-%x SuiteContinuing
-
-%x LongString
 
 %x SingleQuoteString
 %x DoubleQuoteString
@@ -388,7 +395,9 @@ TARGET            ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU
                                       // about what to accept.
 
                                       yyextra->curClassBases.push_back(yytext);
+                                      yyextra->insideBody = true;
                                       generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
+                                      yyextra->insideBody = false;
                                       // codify(yyscanner,yytext);
                                     }
 
@@ -505,10 +514,14 @@ TARGET            ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU
                                       endFontClass(yyscanner);
                                     }
     ({IDENTIFIER}".")*{IDENTIFIER}/"("  {
+                                      yyextra->insideBody = true;
                                       generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
+                                      yyextra->insideBody = false;
                                     }
     ({IDENTIFIER}".")+{IDENTIFIER}  {
+                                      yyextra->insideBody = true;
                                       generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,TRUE);
+                                      yyextra->insideBody = false;
                                     }
     {IDENTIFIER}                    { codify(yyscanner,yytext); }
 
@@ -932,7 +945,6 @@ static int countLines(yyscan_t yyscanner)
   { // last line does not end with a \n, so we add an extra
     // line and explicitly terminate the line after parsing.
     count++;
-    yyextra->needsTermination=TRUE;
   }
   return count;
 }
@@ -1022,7 +1034,7 @@ static void startCodeLine(yyscan_t yyscanner)
     {
       yyextra->currentDefinition = d;
       yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr);
-      //yyextra->insideBody = FALSE;
+      yyextra->insideBody = false;
       yyextra->endComment = FALSE;
       yyextra->searchingForBody = TRUE;
       yyextra->realScope = d->name();
@@ -1035,25 +1047,28 @@ static void startCodeLine(yyscan_t yyscanner)
       {
         yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
                                 yyextra->currentMemberDef->getOutputFileBase(),
-                                yyextra->currentMemberDef->anchor(),yyextra->yyLineNr);
+                                yyextra->currentMemberDef->anchor(),yyextra->yyLineNr,
+                                !yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
       else
       {
         yyextra->code->writeLineNumber(d->getReference(),
                                 d->getOutputFileBase(),
-                                QCString(),yyextra->yyLineNr);
+                                QCString(),yyextra->yyLineNr,
+                                !yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
     }
     else
     {
-      //yyextra->code->codify(lineNumber);
-      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr);
+      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr,
+                                     !yyextra->includeCodeFragment);
     }
-    //yyextra->code->endLineNumber();
   }
   yyextra->code->startCodeLine(yyextra->sourceFileDef);
+  yyextra->insideCodeLine=true;
+
   if (yyextra->currentFontClass)
   {
     yyextra->code->startFontClass(yyextra->currentFontClass);
@@ -1075,6 +1090,7 @@ static void endCodeLine(yyscan_t yyscanner)
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   endFontClass(yyscanner);
   yyextra->code->endCodeLine();
+  yyextra->insideCodeLine=false;
 }
 
 //-------------------------------------------------------------------------------
@@ -1083,7 +1099,10 @@ static void nextCodeLine(yyscan_t yyscanner)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   const char *fc = yyextra->currentFontClass;
-  endCodeLine(yyscanner);
+  if (yyextra->insideCodeLine)
+  {
+    endCodeLine(yyscanner);
+  }
   if (yyextra->yyLineNr<yyextra->inputLines)
   {
     yyextra->currentFontClass = fc;
@@ -1230,7 +1249,7 @@ static bool getLinkInScope(yyscan_t yyscanner,
       //printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p\n",
       //        yyextra->currentDefinition,yyextra->currentMemberDef);
 
-      if (yyextra->currentDefinition && yyextra->currentMemberDef && yyextra->collectXRefs)
+      if (yyextra->currentDefinition && yyextra->currentMemberDef && yyextra->collectXRefs && yyextra->insideBody)
       {
         std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex);
         addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md));
@@ -1341,7 +1360,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
                             md->getBodyDef() : md->getOuterScope();
       if (md->getGroupDef()) d = md->getGroupDef();
       if (d && d->isLinkable() && md->isLinkable() &&
-          yyextra->currentMemberDef && yyextra->collectXRefs)
+          yyextra->currentMemberDef && yyextra->collectXRefs && yyextra->insideBody)
       {
         std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex);
         addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md));
@@ -1369,7 +1388,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
                                 mmd->getBodyDef() : mmd->getOuterScope();
           if (mmd->getGroupDef()) d = mmd->getGroupDef();
           if (d && d->isLinkable() && mmd->isLinkable() &&
-              yyextra->currentMemberDef && yyextra->collectXRefs)
+              yyextra->currentMemberDef && yyextra->collectXRefs && yyextra->insideBody)
           {
             std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex);
             addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(mmd));
@@ -1393,7 +1412,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,
                                   mmd->getBodyDef() : mmd->getOuterScope();
             if (mmd->getGroupDef()) d = mmd->getGroupDef();
             if (d && d->isLinkable() && mmd->isLinkable() &&
-                yyextra->currentMemberDef && yyextra->collectXRefs)
+                yyextra->currentMemberDef && yyextra->collectXRefs && yyextra->insideBody)
             {
               std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex);
               addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(mmd));
@@ -1511,16 +1530,17 @@ static void findMemberLink(yyscan_t yyscanner,
   //    yyextra->currentDefinition?qPrint(yyextra->currentDefinition->name()):"<none>",
   //    yyextra->currentMemberDef?qPrint(yyextra->currentMemberDef->name()):"<none>"
   //    );
+  bool found = false;
   if (yyextra->currentDefinition)
   {
     auto range = Doxygen::symbolMap->find(symName);
     for (auto it = range.first; it!=range.second; ++it)
     {
-      findMemberLink(yyscanner,ol,it->second,symName);
+      if (findMemberLink(yyscanner,ol,it->second,symName)) found = true;
     }
   }
   //printf("sym %s not found\n",&yytext[5]);
-  codify(yyscanner,symName);
+  if (!found) codify(yyscanner,symName);
 }
 
 
@@ -1581,11 +1601,12 @@ void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
 
   if (input.isEmpty()) return;
   printlex(yy_flex_debug, TRUE, __FILE__, fileDef ? qPrint(fileDef->fileName()): NULL);
+  yyextra->fileName      = fileDef ? fileDef->fileName():"";
   yyextra->code = &codeOutIntf;
   yyextra->inputString   = input.data();
   yyextra->inputPosition = 0;
   yyextra->currentFontClass = 0;
-  yyextra->needsTermination = FALSE;
+  yyextra->insideCodeLine = FALSE;
   yyextra->searchCtx=searchCtx;
   yyextra->collectXRefs=collectXRefs;
   if (startLine!=-1)
@@ -1628,7 +1649,7 @@ void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
     // printf("Exited pysourceparser in inconsistent state!\n");
   }
 
-  if (yyextra->needsTermination)
+  if (yyextra->insideCodeLine)
   {
     endCodeLine(yyscanner);
   }
index 38fbe2b..593db6b 100644 (file)
@@ -3,8 +3,8 @@
  * Copyright (C) 1997-2021 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.
  *
 %option extra-type="struct pyscannerYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
 
 /*
- *     includes
+ *      includes
  */
 #include <stdio.h>
 #include <stdlib.h>
@@ -59,6 +63,8 @@
 
 #define USE_STATE2STRING 0
 
+#define unput_string(yytext,yyleng) do { for (int i=(int)yyleng-1;i>=0;i--) unput(yytext[i]); } while(0)
+
 /* ----------------------------------------------------------------- */
 
 struct pyscannerYY_state
@@ -73,7 +79,7 @@ struct pyscannerYY_state
   std::shared_ptr<Entry>  previous;
   std::shared_ptr<Entry>  bodyEntry;
   int                     yyLineNr = 1 ;
-  QCString                yyFileName;
+  QCString                fileName;
   MethodTypes             mtype = Method;
   bool                    stat = FALSE;
   Specifier               virt = Normal;
@@ -140,8 +146,12 @@ static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
 
 //-----------------------------------------------------------------------------
 /* ----------------------------------------------------------------- */
-#undef YY_INPUT
-#define        YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
+#undef  YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
+
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
 
 %}
 
@@ -167,7 +177,7 @@ NONEMPTY          [A-Za-z0-9_\x80-\xFF]
 EXPCHAR           [#(){}\[\],:.%/\\=`*~|&<>!;+-]
 NONEMPTYEXP       [^ \t\n:]
 PARAMNONEMPTY     [^ \t\n():]
-IDENTIFIER        ({LETTER}|"_")({LETTER}|{DIGIT}|"_")*  
+IDENTIFIER        ({LETTER}|"_")({LETTER}|{DIGIT}|"_")*
 SCOPE             {IDENTIFIER}("."{IDENTIFIER})*
 CALL              "("[^)]*")"
 BORDER            ([^A-Za-z0-9])
@@ -185,11 +195,11 @@ LONGSTRINGBLOCK   ({LONGSTRINGITEM}|{SMALLQUOTE})
 SHORTSTRING       ("'"{SHORTSTRINGITEM}*"'"|'"'{SHORTSTRINGITEM}*'"')
 SHORTSTRINGITEM   ({SHORTSTRINGCHAR}|{ESCAPESEQ})
 SHORTSTRINGCHAR   [^\\\n"]
-STRINGLITERAL     {STRINGPREFIX}?( {SHORTSTRING} | {LONGSTRING})  
+STRINGLITERAL     {STRINGPREFIX}?( {SHORTSTRING} | {LONGSTRING})
 STRINGPREFIX      ("r"|"u"|"ur"|"R"|"U"|"UR"|"Ur"|"uR")
 FLOWKW            ("or"|"and"|"is"|"not"|"print"|"for"|"in"|"if"|"try"|"except"|"yield"|"raise"|"break"|"continue"|"pass"|"if"|"return"|"while"|"elif"|"else"|"finally")
-POUNDCOMMENT      "#"[^#\n][^\n]* 
-SCRIPTCOMMENT      "#!".* 
+POUNDCOMMENT      "#"[^#\n][^\n]*
+SCRIPTCOMMENT      "#!".*
 
 STARTDOCSYMS      "##"
 
@@ -204,7 +214,6 @@ STARTDOCSYMS      "##"
 
   /* %x FuncDoubleComment */
   /* %x ClassDoubleComment */
-%x TryClassDocString
 %x TripleComment
 %x SpecialComment
 
@@ -249,111 +258,111 @@ STARTDOCSYMS      "##"
 <Search>{
 
     ^{B}"def"{BB}       { // start of a function/method definition with indent
-                         DBG_CTX((stderr,"Found def at %d\n",yyextra->yyLineNr));
-                         yyextra->indent=computeIndent(yytext);
-                         searchFoundDef(yyscanner);
-                         BEGIN( FunctionDec );
-                       }
+                          DBG_CTX((stderr,"Found def at %d\n",yyextra->yyLineNr));
+                          yyextra->indent=computeIndent(yytext);
+                          searchFoundDef(yyscanner);
+                          BEGIN( FunctionDec );
+                        }
     ^{B}"async"{BB}"def"{BB} { // start of an async function/method definition with indent
-                         DBG_CTX((stderr,"Found async def at %d\n",yyextra->yyLineNr));
-                         yyextra->indent=computeIndent(yytext);
-                         searchFoundDef(yyscanner);
-                         BEGIN( FunctionDec );
-                       }
+                          DBG_CTX((stderr,"Found async def at %d\n",yyextra->yyLineNr));
+                          yyextra->indent=computeIndent(yytext);
+                          searchFoundDef(yyscanner);
+                          BEGIN( FunctionDec );
+                        }
     "def"{BB}           { // start of a function/method definition
-                         searchFoundDef(yyscanner);
-                         BEGIN( FunctionDec );
+                          searchFoundDef(yyscanner);
+                          BEGIN( FunctionDec );
                         }
     "async"{BB}"def"{BB} { // start of a function/method definition
-                         searchFoundDef(yyscanner);
-                         BEGIN( FunctionDec );
+                          searchFoundDef(yyscanner);
+                          BEGIN( FunctionDec );
                         }
 
-     ^{B}"class"{BB}   { // start of a class definition with indent
-                                 DBG_CTX((stderr,"Found class at %d\n",yyextra->yyLineNr));
-                         yyextra->indent=computeIndent(yytext);
-                         searchFoundClass(yyscanner);
-                         BEGIN( ClassDec ) ;
-                               }
+     ^{B}"class"{BB}    { // start of a class definition with indent
+                          DBG_CTX((stderr,"Found class at %d\n",yyextra->yyLineNr));
+                          yyextra->indent=computeIndent(yytext);
+                          searchFoundClass(yyscanner);
+                          BEGIN( ClassDec ) ;
+                        }
      "class"{BB}        {  // start of a class definition
-                         searchFoundClass(yyscanner);
-                         BEGIN( ClassDec ) ;
+                          searchFoundClass(yyscanner);
+                          BEGIN( ClassDec ) ;
                        }
      ^{B}"from"{BB}    |
-     "from"{BB}               { // start of an from import
-                         yyextra->packageCommentAllowed = FALSE;
+     "from"{BB}        { // start of an from import
+                          yyextra->packageCommentAllowed = FALSE;
                           BEGIN( FromMod );
                        }
 
      ^{B}"import"{BB}  |
      "import"{BB}      { // start of an import statement
-                         yyextra->packageCommentAllowed = FALSE;
+                          yyextra->packageCommentAllowed = FALSE;
                           BEGIN( Import );
                        }
      ^{B}{IDENTIFIER}/{B}"="{B}"property" { // property
-                       yyextra->current->section   = Entry::VARIABLE_SEC;
-                       yyextra->current->mtype     = Property;
-                       yyextra->current->name      = QCString(yytext).stripWhiteSpace();
-                       yyextra->current->fileName  = yyextra->yyFileName;
-                       yyextra->current->startLine = yyextra->yyLineNr;
-                       yyextra->current->bodyLine  = yyextra->yyLineNr;
-                       yyextra->packageCommentAllowed = FALSE;
-                       BEGIN(VariableDec);
-                             }
+                        yyextra->current->section   = Entry::VARIABLE_SEC;
+                        yyextra->current->mtype     = Property;
+                        yyextra->current->name      = QCString(yytext).stripWhiteSpace();
+                        yyextra->current->fileName  = yyextra->fileName;
+                        yyextra->current->startLine = yyextra->yyLineNr;
+                        yyextra->current->bodyLine  = yyextra->yyLineNr;
+                        yyextra->packageCommentAllowed = FALSE;
+                        BEGIN(VariableDec);
+                      }
      ^{B}{IDENTIFIER}/{B}"="[^=] { // variable
                         if (yyextra->search_count) REJECT;
-                       yyextra->indent=computeIndent(yytext);
-                       yyextra->current->section   = Entry::VARIABLE_SEC;
-                       yyextra->current->name      = QCString(yytext).stripWhiteSpace();
-                       yyextra->current->fileName  = yyextra->yyFileName;
-                       yyextra->current->startLine = yyextra->yyLineNr;
-                       yyextra->current->bodyLine  = yyextra->yyLineNr;
-                       yyextra->packageCommentAllowed = FALSE;
-                       BEGIN(VariableDec);
-                     }
+                        yyextra->indent=computeIndent(yytext);
+                        yyextra->current->section   = Entry::VARIABLE_SEC;
+                        yyextra->current->name      = QCString(yytext).stripWhiteSpace();
+                        yyextra->current->fileName  = yyextra->fileName;
+                        yyextra->current->startLine = yyextra->yyLineNr;
+                        yyextra->current->bodyLine  = yyextra->yyLineNr;
+                        yyextra->packageCommentAllowed = FALSE;
+                        BEGIN(VariableDec);
+                      }
      {B}{IDENTIFIER}/({B},{B}{IDENTIFIER})*{B}")"*{B}"="[^=] { // list of variables, we cannot place the default value
                                                                // so we will skip it later on in a general rule
                                                                // Also note ")" this is to catch also (a,b). the "("
                                                                // is caught in the rule: [(], the ")" will be handled in [)]
                         if (yyextra->search_count > 1) REJECT;
-                       yyextra->indent=computeIndent(yytext);
-                       yyextra->current->section   = Entry::VARIABLE_SEC;
-                       yyextra->current->name      = QCString(yytext).stripWhiteSpace();
-                       yyextra->current->fileName  = yyextra->yyFileName;
-                       yyextra->current->startLine = yyextra->yyLineNr;
-                       yyextra->current->bodyLine  = yyextra->yyLineNr;
-                       yyextra->packageCommentAllowed = FALSE;
-                       newVariable(yyscanner);
-                     }
-     "'"             { // start of a single quoted string
-                               yyextra->stringContext=YY_START;
-                       yyextra->copyString=0;
-                       yyextra->packageCommentAllowed = FALSE;
+                        yyextra->indent=computeIndent(yytext);
+                        yyextra->current->section   = Entry::VARIABLE_SEC;
+                        yyextra->current->name      = QCString(yytext).stripWhiteSpace();
+                        yyextra->current->fileName  = yyextra->fileName;
+                        yyextra->current->startLine = yyextra->yyLineNr;
+                        yyextra->current->bodyLine  = yyextra->yyLineNr;
+                        yyextra->packageCommentAllowed = FALSE;
+                        newVariable(yyscanner);
+                      }
+     "'"              { // start of a single quoted string
+                        yyextra->stringContext=YY_START;
+                        yyextra->copyString=0;
+                        yyextra->packageCommentAllowed = FALSE;
                         BEGIN( SingleQuoteString );
                       }
-     "\""            { // start of a double quoted string
-                               yyextra->stringContext=YY_START;
-                       yyextra->copyString=0;
-                       yyextra->packageCommentAllowed = FALSE;
+     "\""             { // start of a double quoted string
+                        yyextra->stringContext=YY_START;
+                        yyextra->copyString=0;
+                        yyextra->packageCommentAllowed = FALSE;
                         BEGIN( DoubleQuoteString );
                       }
     "@staticmethod"  {
-                               yyextra->stat=TRUE;
-                     }
+                        yyextra->stat=TRUE;
+                      }
     "@"{SCOPE}{CALL}? { // decorator
                         lineCount(yyscanner);
                       }
     {SCRIPTCOMMENT}   { // Unix type script comment
                         if (yyextra->yyLineNr != 1) REJECT;
-                     }
-    {POUNDCOMMENT}    { // normal comment 
-                       yyextra->packageCommentAllowed = FALSE;
-                     }
+                      }
+    {POUNDCOMMENT}    { // normal comment
+                        yyextra->packageCommentAllowed = FALSE;
+                      }
     {IDENTIFIER}      { // some other identifier
-                       yyextra->packageCommentAllowed = FALSE;
-                     }
-    ^{BB}            {
-                       yyextra->curIndent=computeIndent(yytext);
+                        yyextra->packageCommentAllowed = FALSE;
+                      }
+    ^{BB}             {
+                        yyextra->curIndent=computeIndent(yytext);
                       }
 
     {NEWLINE}+        { // new line
@@ -361,20 +370,20 @@ STARTDOCSYMS      "##"
                       }
 
     {TRIDOUBLEQUOTE}  { // start of a comment block
-                       initTriDoubleQuoteBlock(yyscanner);
-                       BEGIN(TripleComment);
+                        initTriDoubleQuoteBlock(yyscanner);
+                        BEGIN(TripleComment);
                       }
 
     {TRISINGLEQUOTE}  { // start of a comment block
-                       initTriSingleQuoteBlock(yyscanner);
-                       BEGIN(TripleComment);
+                        initTriSingleQuoteBlock(yyscanner);
+                        BEGIN(TripleComment);
                       }
 
     {STARTDOCSYMS}/[^#]    {  // start of a special comment
-                       yyextra->curIndent=computeIndent(yytext);
-                       yyextra->packageCommentAllowed = FALSE;
-                       initSpecialBlock(yyscanner);
-                       BEGIN(SpecialComment);
+                        yyextra->curIndent=computeIndent(yytext);
+                        yyextra->packageCommentAllowed = FALSE;
+                        initSpecialBlock(yyscanner);
+                        BEGIN(SpecialComment);
                       }
     [(]               { // we have to do something with (
                         yyextra->search_count += 1;
@@ -392,18 +401,18 @@ STARTDOCSYMS      "##"
 <FromMod>{
   "."                 { // python3 style imports
                       }
-  {IDENTIFIER}({B}"."{B}{IDENTIFIER})* { // from package import 
+  {IDENTIFIER}({B}"."{B}{IDENTIFIER})* { // from package import
                         yyextra->packageName=yytext;
-                     }
-  "import"{B}        {
-                       BEGIN(FromModItem);
-                     }
-  \n                 {
+                      }
+  "import"{B}         {
+                        BEGIN(FromModItem);
+                      }
+  \n                  {
                         incLineNr(yyscanner);
                         BEGIN(Search);
                       }
-  {B}                {
-                     }
+  {B}                 {
+                      }
   .                   {
                         unput(*yytext);
                         BEGIN(Search);
@@ -411,13 +420,13 @@ STARTDOCSYMS      "##"
 }
 
 <FromModItem>{
-  "*"          { // import all
+  "*"           { // import all
                   addFrom(yyscanner,TRUE);
                   BEGIN(Search);
-               }
+                }
   {IDENTIFIER}/{B}","{B} {
                   addFrom(yyscanner,FALSE);
-               }
+                }
   {IDENTIFIER}/{B}")" {
                   addFrom(yyscanner,FALSE);
                 }
@@ -427,16 +436,16 @@ STARTDOCSYMS      "##"
                   {
                     BEGIN(Search);
                   }
-               }
-  \n           {
+                }
+  \n            {
                   incLineNr(yyscanner);
                   if (!yyextra->importTuple)
                   {
                     BEGIN(Search);
                   }
                 }
-  {B}          {
-               }
+  {B}           {
+                }
   "("           {
                   yyextra->importTuple=TRUE;
                 }
@@ -444,8 +453,8 @@ STARTDOCSYMS      "##"
                   yyextra->importTuple=FALSE;
                   BEGIN(Search);
                 }
-  ","          {
-               }
+  ","           {
+                }
   "\\"{B}\n     { // line continuation
                   incLineNr(yyscanner);
                 }
@@ -457,20 +466,20 @@ STARTDOCSYMS      "##"
 
 <Import>{
   {IDENTIFIER}({B}"."{B}{IDENTIFIER})* {
-                       yyextra->current->name=removeRedundantWhiteSpace(substitute(yytext,".","::"));
-                       yyextra->current->fileName = yyextra->yyFileName; 
-                       //printf("Adding using declaration: found:%s:%d name=%s\n",qPrint(yyextra->yyFileName),yyextra->yyLineNr,qPrint(yyextra->current->name));
-                       yyextra->current->section=Entry::USINGDECL_SEC;
-                       yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
-                       initEntry(yyscanner);
-                       BEGIN(Search);
-                      }
-  \n           {
+                        yyextra->current->name=removeRedundantWhiteSpace(substitute(yytext,".","::"));
+                        yyextra->current->fileName = yyextra->fileName;
+                        //printf("Adding using declaration: found:%s:%d name=%s\n",qPrint(yyextra->fileName),yyextra->yyLineNr,qPrint(yyextra->current->name));
+                        yyextra->current->section=Entry::USINGDECL_SEC;
+                        yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
+                        initEntry(yyscanner);
+                        BEGIN(Search);
+                      }
+  \n            {
                   incLineNr(yyscanner);
                   BEGIN(Search);
                 }
-  {B}          {
-               }
+  {B}           {
+                }
   .             {
                   unput(*yytext);
                   BEGIN(Search);
@@ -480,59 +489,59 @@ STARTDOCSYMS      "##"
 <SearchMemVars>{
     "self."{IDENTIFIER}/{B}"=" {
                         DBG_CTX((stderr,"Found instance method variable %s in %s at %d\n",&yytext[5],qPrint(yyextra->current_root->name.data(),yyextra->yyLineNr)));
-                       yyextra->current->name=&yytext[5];
-                       yyextra->current->section=Entry::VARIABLE_SEC;
-                       yyextra->current->fileName  = yyextra->yyFileName;
-                       yyextra->current->startLine = yyextra->yyLineNr;
-                       yyextra->current->bodyLine  = yyextra->yyLineNr;
-                       yyextra->current->type.resize(0);
-                       if (yyextra->current->name.at(0)=='_') // mark as private
-                       {
-                         yyextra->current->protection=Private;
-                       }
-                       newEntry(yyscanner);
+                        yyextra->current->name=&yytext[5];
+                        yyextra->current->section=Entry::VARIABLE_SEC;
+                        yyextra->current->fileName  = yyextra->fileName;
+                        yyextra->current->startLine = yyextra->yyLineNr;
+                        yyextra->current->bodyLine  = yyextra->yyLineNr;
+                        yyextra->current->type.resize(0);
+                        if (yyextra->current->name.at(0)=='_') // mark as private
+                        {
+                          yyextra->current->protection=Private;
+                        }
+                        newEntry(yyscanner);
                       }
     "cls."{IDENTIFIER}/{B}"=" {
                         DBG_CTX((stderr,"Found class method variable %s in %s at %d\n",&yytext[4],qPrint(yyextra->current_root->name),yyextra->yyLineNr));
-                       yyextra->current->name=&yytext[4];
-                       yyextra->current->section=Entry::VARIABLE_SEC;
-                       yyextra->current->fileName  = yyextra->yyFileName;
-                       yyextra->current->startLine = yyextra->yyLineNr;
-                       yyextra->current->bodyLine  = yyextra->yyLineNr;
-                       yyextra->current->type.resize(0);
-                       if (yyextra->current->name.at(0)=='_') // mark as private
-                       {
-                         yyextra->current->protection=Private;
-                       }
-                       newEntry(yyscanner);
+                        yyextra->current->name=&yytext[4];
+                        yyextra->current->section=Entry::VARIABLE_SEC;
+                        yyextra->current->fileName  = yyextra->fileName;
+                        yyextra->current->startLine = yyextra->yyLineNr;
+                        yyextra->current->bodyLine  = yyextra->yyLineNr;
+                        yyextra->current->type.resize(0);
+                        if (yyextra->current->name.at(0)=='_') // mark as private
+                        {
+                          yyextra->current->protection=Private;
+                        }
+                        newEntry(yyscanner);
                       }
     {TRIDOUBLEQUOTE}  { // start of a comment block
-                       initTriDoubleQuoteBlock(yyscanner);
-                       BEGIN(TripleComment);
+                        initTriDoubleQuoteBlock(yyscanner);
+                        BEGIN(TripleComment);
                       }
 
     {TRISINGLEQUOTE}  { // start of a comment block
-                       initTriSingleQuoteBlock(yyscanner);
-                       BEGIN(TripleComment);
+                        initTriSingleQuoteBlock(yyscanner);
+                        BEGIN(TripleComment);
                       }
 
     {STARTDOCSYMS}/[^#]    {  // start of a special comment
-                       initSpecialBlock(yyscanner);
-                       BEGIN(SpecialComment);
+                        initSpecialBlock(yyscanner);
+                        BEGIN(SpecialComment);
                       }
     {POUNDCOMMENT}    { // #
-                     }
-    "'"                      { // start of a single quoted string
-                               yyextra->stringContext=YY_START;
-                       yyextra->copyString=0;
+                      }
+    "'"               { // start of a single quoted string
+                        yyextra->stringContext=YY_START;
+                        yyextra->copyString=0;
                         BEGIN( SingleQuoteString );
                       }
     "\""              { // start of a double quoted string
-                               yyextra->stringContext=YY_START;
-                       yyextra->copyString=0;
+                        yyextra->stringContext=YY_START;
+                        yyextra->copyString=0;
                         BEGIN( DoubleQuoteString );
                       }
-    \n               { incLineNr(yyscanner); }
+    \n                { incLineNr(yyscanner); }
     {IDENTIFIER}      // identifiers
     [^'"\.#a-z_A-Z\n]+  // other uninteresting stuff
     .                 // anything else
@@ -541,145 +550,137 @@ STARTDOCSYMS      "##"
 <FunctionBody>{
     \n{B}/{IDENTIFIER}{BB}  {
                         DBG_CTX((stderr,"indent %d<=%d\n",computeIndent(&yytext[1]),yyextra->indent));
-                        if (computeIndent(&yytext[1])<=yyextra->indent) 
-                       {
-                         int i;
-                         for (i=(int)yyleng-1;i>=0;i--)
-                         {
-                           unput(yytext[i]);
-                         }
-                         endOfDef(yyscanner);
-                         //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
+                        if (computeIndent(&yytext[1])<=yyextra->indent)
+                        {
+                          unput_string(yytext,yyleng);
+                          endOfDef(yyscanner);
+                          //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
                           BEGIN(Search);
-                       }
-                       else
-                       {
+                        }
+                        else
+                        {
                           incLineNr(yyscanner);
-                         yyextra->current->program << yytext;
-                       }
+                          yyextra->current->program << yytext;
+                        }
                       }
-    \n{B}/"##"       {
+    \n{B}/"##"        {
                         if (computeIndent(&yytext[1])<=yyextra->indent)
-                       {
-                         int i;
-                         for (i=(int)yyleng-1;i>=0;i--)
-                         {
-                           unput(yytext[i]);
-                         }
-                         endOfDef(yyscanner);
-                         //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
+                        {
+                          unput_string(yytext,yyleng);
+                          endOfDef(yyscanner);
+                          //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
                           BEGIN(Search);
-                       }
-                       else
-                       {
-                         incLineNr(yyscanner);
-                         yyextra->current->program << yytext;
-                       }
-                     }
-    <<EOF>>          {
-                       endOfDef(yyscanner);
-                       yyterminate();
-                     }
-    ^{BB}/\n         { // skip empty line
-                       yyextra->current->program << yytext;
-                     }
-    ^{BB}            { // something at indent >0
-                       yyextra->current->program << yytext;
-                       yyextra->curIndent = computeIndent(yytext);
-                        if (yyextra->curIndent<=yyextra->indent) 
-                         // jumped out of the function
-                       {
-                         endOfDef(yyscanner,1);
+                        }
+                        else
+                        {
+                          incLineNr(yyscanner);
+                          yyextra->current->program << yytext;
+                        }
+                      }
+    <<EOF>>           {
+                        endOfDef(yyscanner);
+                        yyterminate();
+                      }
+    ^{BB}/\n          { // skip empty line
+                        yyextra->current->program << yytext;
+                      }
+    ^{BB}             { // something at indent >0
+                        yyextra->current->program << yytext;
+                        yyextra->curIndent = computeIndent(yytext);
+                        if (yyextra->curIndent<=yyextra->indent)
+                          // jumped out of the function
+                        {
+                          endOfDef(yyscanner,1);
                           BEGIN(Search);
-                       }
-                     }
-    "'"                      { // start of a single quoted string
-                       yyextra->current->program << yytext;
-                               yyextra->stringContext=YY_START;
-                       yyextra->specialBlock = FALSE; 
-                       yyextra->copyString=&yyextra->current->program;
+                        }
+                      }
+    "'"               { // start of a single quoted string
+                        yyextra->current->program << yytext;
+                        yyextra->stringContext=YY_START;
+                        yyextra->specialBlock = FALSE;
+                        yyextra->copyString=&yyextra->current->program;
                         BEGIN( SingleQuoteString );
                       }
     "\""              { // start of a double quoted string
-                       yyextra->current->program << yytext;
-                               yyextra->stringContext=YY_START;
-                       yyextra->specialBlock = FALSE; 
-                       yyextra->copyString=&yyextra->current->program;
+                        yyextra->current->program << yytext;
+                        yyextra->stringContext=YY_START;
+                        yyextra->specialBlock = FALSE;
+                        yyextra->copyString=&yyextra->current->program;
                         BEGIN( DoubleQuoteString );
                       }
     [^ \t\n#'".]+     { // non-special stuff
-                       yyextra->current->program << yytext;
-                       yyextra->specialBlock = FALSE; 
+                        yyextra->current->program << yytext;
+                        yyextra->specialBlock = FALSE;
+                      }
+    ^{POUNDCOMMENT}   { // normal comment
+                        yyextra->current->program << yytext;
                       }
-    ^{POUNDCOMMENT}   { // normal comment 
-                       yyextra->current->program << yytext;
-                     }
     "#".*             { // comment half way
-                       yyextra->current->program << yytext;
+                        yyextra->current->program << yytext;
+                      }
+    {NEWLINE}         {
+                        incLineNr(yyscanner);
+                        yyextra->current->program << yytext;
                       }
-    {NEWLINE}        { 
-                       incLineNr(yyscanner); 
-                       yyextra->current->program << yytext;
-                     }
     .                 { // any character
-                       yyextra->current->program << *yytext;
-                       yyextra->specialBlock = FALSE; 
+                        yyextra->current->program << *yytext;
+                        yyextra->specialBlock = FALSE;
                       }
 
     {TRIDOUBLEQUOTE}  { // start of a comment block
-                       yyextra->current->program << yytext;
-                       initTriDoubleQuoteBlock(yyscanner);
-                       BEGIN(TripleComment);
+                        yyextra->current->program << yytext;
+                        initTriDoubleQuoteBlock(yyscanner);
+                        BEGIN(TripleComment);
                       }
 
     {TRISINGLEQUOTE}  { // start of a comment block
-                       yyextra->current->program << yytext;
-                       initTriSingleQuoteBlock(yyscanner);
-                       BEGIN(TripleComment);
+                        yyextra->current->program << yytext;
+                        initTriSingleQuoteBlock(yyscanner);
+                        BEGIN(TripleComment);
                       }
 
     {STARTDOCSYMS}/[^#]  {  // start of a special comment
-                       initSpecialBlock(yyscanner);
-                       BEGIN(SpecialComment);
+                        initSpecialBlock(yyscanner);
+                        BEGIN(SpecialComment);
                       }
-    
+
 }
 
 <FunctionDec>{
     {IDENTIFIER}            {
-                             //found function name
-                             if (yyextra->current->type.isEmpty()) 
-                             {
-                                 yyextra->current->type = "def";
-                             }
-                             yyextra->current->name = yytext;
-                             yyextra->current->name = yyextra->current->name.stripWhiteSpace();
-                             newFunction(yyscanner);
+                              //found function name
+                              if (yyextra->current->type.isEmpty())
+                              {
+                                  yyextra->current->type = "def";
+                              }
+                              yyextra->current->name = yytext;
+                              yyextra->current->name = yyextra->current->name.stripWhiteSpace();
+                              newFunction(yyscanner);
                             }
-    {B}":"{B}              { // function without arguments
-                             yyextra->specialBlock = TRUE; // expecting a docstring
-                             yyextra->bodyEntry = yyextra->current;
+    {B}":"{B}               { // function without arguments
+                              yyextra->specialBlock = TRUE; // expecting a docstring
+                              yyextra->bodyEntry = yyextra->current;
                               yyextra->current->bodyLine  = yyextra->yyLineNr;
                               BEGIN(FunctionBody);
-                           }
+                            }
 
     "->"                    {
-                             yyextra->defVal.str(std::string());
-                             yyextra->braceCount = 0;
-                             BEGIN(FunctionTypeAnnotation);
-                           }
+                              yyextra->defVal.str(std::string());
+                              yyextra->braceCount = 0;
+                              BEGIN(FunctionTypeAnnotation);
+                            }
     {B}"("                  {
-                             yyextra->funcParamsEnd = FALSE;
+                              yyextra->funcParamsEnd = FALSE;
                               yyextra->current->bodyLine  = yyextra->yyLineNr;
-                             BEGIN(FunctionParams);
-                           }
+                              BEGIN(FunctionParams);
+                            }
     ")"                     { // end of parameter list
                               if (yyextra->current->argList.empty())
                               {
                                 yyextra->current->argList.setNoParameters(TRUE);
                               }
-                             yyextra->current->args = argListToString(yyextra->current->argList);
-                             yyextra->funcParamsEnd = TRUE;
+                              yyextra->current->args = argListToString(yyextra->current->argList);
+                              yyextra->funcParamsEnd = TRUE;
                             }
 }
 
@@ -691,160 +692,160 @@ STARTDOCSYMS      "##"
                           yyextra->argType = yytext;
                         }
     {IDENTIFIER}        { // Name of parameter
-                         lineCount(yyscanner);
-                         Argument a;
-                         a.name = QCString(yytext).stripWhiteSpace();
-                         a.type = yyextra->argType;
-                         yyextra->current->argList.push_back(a);
+                          lineCount(yyscanner);
+                          Argument a;
+                          a.name = QCString(yytext).stripWhiteSpace();
+                          a.type = yyextra->argType;
+                          yyextra->current->argList.push_back(a);
                           yyextra->argType = "";
                         }
-    "="                        { // default value
+    "="                 { // default value
                           // TODO: this rule is too simple, need to be able to
                           // match things like =")" as well!
-                         yyextra->defVal.str(std::string());
-                         yyextra->braceCount = 0;
-                         BEGIN(FunctionParamDefVal);
-                       }
+                          yyextra->defVal.str(std::string());
+                          yyextra->braceCount = 0;
+                          BEGIN(FunctionParamDefVal);
+                        }
      ")"                {
-                         unput(*yytext);
-                         BEGIN(FunctionDec);
+                          unput(*yytext);
+                          BEGIN(FunctionDec);
                         }
      ":"{B}             {
-                         yyextra->defVal.str(std::string());
-                         yyextra->braceCount = 0;
-                         BEGIN(FunctionAnnotation);
-                       }
-    {POUNDCOMMENT}     { // a comment
-                       }
+                          yyextra->defVal.str(std::string());
+                          yyextra->braceCount = 0;
+                          BEGIN(FunctionAnnotation);
+                        }
+    {POUNDCOMMENT}      { // a comment
+                        }
     {PARAMNONEMPTY}     { // Default rule inside arguments.
                         }
 
 }
 
 <FunctionTypeAnnotation>{
-     "{"               |
-     "["               |
-     "("               {
-                         ++yyextra->braceCount;
-                         yyextra->defVal << *yytext;
-                       }
-     "}"               |
-     "]"               |
-     ")"               {
-                         --yyextra->braceCount;
-                         yyextra->defVal << *yytext;
-                               }
-     ":"               {
-                         if (yyextra->braceCount == 0)
-                         {
-                           yyextra->current->type = yyextra->defVal.str();
-                           unput(*yytext);
-                           BEGIN(FunctionDec);
-                         }
-                         else
-                           yyextra->defVal << *yytext;
-                               }
+     "{"                |
+     "["                |
+     "("                {
+                          ++yyextra->braceCount;
+                          yyextra->defVal << *yytext;
+                        }
+     "}"                |
+     "]"                |
+     ")"                {
+                          --yyextra->braceCount;
+                          yyextra->defVal << *yytext;
+                        }
+     ":"                {
+                          if (yyextra->braceCount == 0)
+                          {
+                            yyextra->current->type = yyextra->defVal.str();
+                            unput(*yytext);
+                            BEGIN(FunctionDec);
+                          }
+                          else
+                            yyextra->defVal << *yytext;
+                        }
      "'"                {
-                         yyextra->defVal << *yytext;
-                         yyextra->copyString=&yyextra->defVal;
-                         yyextra->stringContext=FunctionTypeAnnotation;
-                         BEGIN(SingleQuoteString);
+                          yyextra->defVal << *yytext;
+                          yyextra->copyString=&yyextra->defVal;
+                          yyextra->stringContext=FunctionTypeAnnotation;
+                          BEGIN(SingleQuoteString);
                         }
      "\""               {
-                         yyextra->defVal << *yytext;
-                         yyextra->copyString=&yyextra->defVal;
-                         yyextra->stringContext=FunctionTypeAnnotation;
-                         BEGIN(DoubleQuoteString);
+                          yyextra->defVal << *yytext;
+                          yyextra->copyString=&yyextra->defVal;
+                          yyextra->stringContext=FunctionTypeAnnotation;
+                          BEGIN(DoubleQuoteString);
                         }
      \n                 {
-                         yyextra->defVal << *yytext;
-                         incLineNr(yyscanner);
-                       }
-     .                 {
-                         yyextra->defVal << *yytext;
-                               }
+                          yyextra->defVal << *yytext;
+                          incLineNr(yyscanner);
+                        }
+     .                  {
+                          yyextra->defVal << *yytext;
+                        }
 }
 
 <FunctionAnnotation>{
-     "{"               |
-     "["               |
-     "("               {
-                         ++yyextra->braceCount;
-                         yyextra->defVal << *yytext;
-                       }
-     "}"               |
-     "]"               {
-                         --yyextra->braceCount;
-                         yyextra->defVal << *yytext;
-                               }
-     ")"               |
-     "="               |
-     ","               {
-                         if (yyextra->braceCount == 0)
-                         {
-                           if (!yyextra->current->argList.empty())
-                             yyextra->current->argList.back().type += yyextra->defVal.str();
-                           if (*yytext != ',')
-                             unput(*yytext);
-                           BEGIN(FunctionParams);
-                         }
-                         else
-                         {
-                           if (*yytext == ')')
-                             --yyextra->braceCount;
-                           yyextra->defVal << *yytext;
-                         }
-                               }
+     "{"                |
+     "["                |
+     "("                {
+                          ++yyextra->braceCount;
+                          yyextra->defVal << *yytext;
+                        }
+     "}"                |
+     "]"                {
+                          --yyextra->braceCount;
+                          yyextra->defVal << *yytext;
+                        }
+     ")"                |
+     "="                |
+     ","                {
+                          if (yyextra->braceCount == 0)
+                          {
+                            if (!yyextra->current->argList.empty())
+                              yyextra->current->argList.back().type += yyextra->defVal.str();
+                            if (*yytext != ',')
+                              unput(*yytext);
+                            BEGIN(FunctionParams);
+                          }
+                          else
+                          {
+                            if (*yytext == ')')
+                              --yyextra->braceCount;
+                            yyextra->defVal << *yytext;
+                          }
+                        }
      "'"                {
-                         yyextra->defVal << *yytext;
-                         yyextra->copyString=&yyextra->defVal;
-                         yyextra->stringContext=FunctionAnnotation;
-                         BEGIN(SingleQuoteString);
+                          yyextra->defVal << *yytext;
+                          yyextra->copyString=&yyextra->defVal;
+                          yyextra->stringContext=FunctionAnnotation;
+                          BEGIN(SingleQuoteString);
                         }
      "\""               {
-                         yyextra->defVal << *yytext;
-                         yyextra->copyString=&yyextra->defVal;
-                         yyextra->stringContext=FunctionAnnotation;
-                         BEGIN(DoubleQuoteString);
+                          yyextra->defVal << *yytext;
+                          yyextra->copyString=&yyextra->defVal;
+                          yyextra->stringContext=FunctionAnnotation;
+                          BEGIN(DoubleQuoteString);
                         }
      \n                 {
-                         yyextra->defVal << *yytext;
-                         incLineNr(yyscanner);
-                               }
-     .                 {
-                         yyextra->defVal << *yytext;
-                               }
+                          yyextra->defVal << *yytext;
+                          incLineNr(yyscanner);
+                        }
+     .                  {
+                          yyextra->defVal << *yytext;
+                        }
 }
 
 <FunctionParamDefVal>{
-     "{"               
-     "["               
-     "("               { // internal opening brace, assumption is that we have correct code so braces do match
-                                 ++yyextra->braceCount;
-                         yyextra->defVal << *yytext;
-                               }
-     "}"               |
-     "]"               {
-                         --yyextra->braceCount;
-                         yyextra->defVal << *yytext;
-                               }
-     ")"               |
-     ","               {
-                         if (yyextra->braceCount == 0)
-                         {
-                           if (!yyextra->current->argList.empty())
-                             yyextra->current->argList.back().defval=QCString(yyextra->defVal.str()).stripWhiteSpace();
-                           if (*yytext == ')')
-                             unput(*yytext);
-                           BEGIN(FunctionParams);
-                         }
-                         else
-                         {
-                           if (*yytext == ')')
-                             --yyextra->braceCount;
-                           yyextra->defVal << *yytext;
-                         }
-                               }
+     "{"                |
+     "["                |
+     "("                { // internal opening brace, assumption is that we have correct code so braces do match
+                          ++yyextra->braceCount;
+                          yyextra->defVal << *yytext;
+                        }
+     "}"                |
+     "]"                {
+                          --yyextra->braceCount;
+                          yyextra->defVal << *yytext;
+                        }
+     ")"                |
+     ","                {
+                          if (yyextra->braceCount == 0)
+                          {
+                            if (!yyextra->current->argList.empty())
+                              yyextra->current->argList.back().defval=QCString(yyextra->defVal.str()).stripWhiteSpace();
+                            if (*yytext == ')')
+                              unput(*yytext);
+                            BEGIN(FunctionParams);
+                          }
+                          else
+                          {
+                            if (*yytext == ')')
+                              --yyextra->braceCount;
+                            yyextra->defVal << *yytext;
+                          }
+                        }
 
      "'"                {
                           yyextra->defVal << *yytext;
@@ -859,124 +860,146 @@ STARTDOCSYMS      "##"
                           BEGIN( DoubleQuoteString );
                         }
      \n                 {
-                                   yyextra->defVal << *yytext;
-                           incLineNr(yyscanner);
-                               }
-     .                 {
-                           yyextra->defVal << *yytext;
-                               }
+                            yyextra->defVal << *yytext;
+                            incLineNr(yyscanner);
+                        }
+     .                  {
+                            yyextra->defVal << *yytext;
+                        }
 }
 
 
 <ClassBody>{
     \n/{IDENTIFIER}{BB}  { // new def at indent 0
-                        incLineNr(yyscanner);
-                       endOfDef(yyscanner);
-                       //yyextra->hideClassDocs = FALSE;
-                       //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
-                        BEGIN(Search);
+                        if (computeIndent(&yytext[1])<=yyextra->indent)
+                        {
+                          int i;
+                          for (i=(int)yyleng-1;i>=0;i--)
+                          {
+                            unput(yytext[i]);
+                          }
+                          endOfDef(yyscanner);
+                          //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
+                          BEGIN(Search);
+                        }
+                        else
+                        {
+                          incLineNr(yyscanner);
+                          yyextra->current->program << yytext;
+                        }
                       }
     \n/"##"[^#]       {  // start of a special comment at indent 0
-                        incLineNr(yyscanner);
-                       endOfDef(yyscanner);
-                       //yyextra->hideClassDocs = FALSE;
-                       //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
-                        BEGIN(Search);
+                        if (computeIndent(&yytext[1])<=yyextra->indent)
+                        {
+                          int i;
+                          for (i=(int)yyleng-1;i>=0;i--)
+                          {
+                            unput(yytext[i]);
+                          }
+                          endOfDef(yyscanner);
+                          //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
+                          BEGIN(Search);
+                        }
+                        else
+                        {
+                          incLineNr(yyscanner);
+                          yyextra->current->program << yytext;
+                        }
+                      }
+    ^{BB}/\n          { // skip empty line
+                        yyextra->current->program << yytext;
+                      }
+    <<EOF>>           {
+                        endOfDef(yyscanner);
+                        yyterminate();
                       }
-    ^{BB}/\n         { // skip empty line
-                       yyextra->current->program << yytext;
-                     }
-    <<EOF>>          {
-                       endOfDef(yyscanner);
-                       yyterminate();
-                     }
-    ^{BB}            { // something at indent >0
+    ^{BB}             { // something at indent >0
                         yyextra->curIndent=computeIndent(yytext);
-                       DBG_CTX((stderr,"yyextra->curIndent=%d yyextra->indent=%d\n",yyextra->curIndent,yyextra->indent));
-                        if (yyextra->curIndent<=yyextra->indent) 
-                         // jumped out of the class/method
-                       {
-                         endOfDef(yyscanner,1);
-                         yyextra->indent=yyextra->curIndent;
-                         // make sure the next rule matches ^...
-                         //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
-                         //yyextra->hideClassDocs = FALSE;
+                        DBG_CTX((stderr,"yyextra->curIndent=%d yyextra->indent=%d\n",yyextra->curIndent,yyextra->indent));
+                        if (yyextra->curIndent<=yyextra->indent)
+                          // jumped out of the class/method
+                        {
+                          endOfDef(yyscanner,1);
+                          yyextra->indent=yyextra->curIndent;
+                          // make sure the next rule matches ^...
+                          //YY_CURRENT_BUFFER->yy_at_bol=TRUE;
+                          //yyextra->hideClassDocs = FALSE;
                           BEGIN(Search);
-                       }
-                       else
-                       {
-                         yyextra->current->program << yytext;
-                       }
-                     }
-    "'"                      { // start of a single quoted string
-                       yyextra->current->program << *yytext;
-                               yyextra->stringContext=YY_START;
-                       yyextra->specialBlock = FALSE; 
-                       yyextra->copyString=&yyextra->current->program;
+                        }
+                        else
+                        {
+                          yyextra->current->program << yytext;
+                        }
+                      }
+    "'"               { // start of a single quoted string
+                        yyextra->current->program << *yytext;
+                        yyextra->stringContext=YY_START;
+                        yyextra->specialBlock = FALSE;
+                        yyextra->copyString=&yyextra->current->program;
                         BEGIN( SingleQuoteString );
                       }
     "\""              { // start of a double quoted string
-                       yyextra->current->program << *yytext;
-                               yyextra->stringContext=YY_START;
-                       yyextra->specialBlock = FALSE; 
-                       yyextra->copyString=&yyextra->current->program;
+                        yyextra->current->program << *yytext;
+                        yyextra->stringContext=YY_START;
+                        yyextra->specialBlock = FALSE;
+                        yyextra->copyString=&yyextra->current->program;
                         BEGIN( DoubleQuoteString );
                       }
     [^ \t\n#'"]+      { // non-special stuff
-                       yyextra->current->program << yytext;
-                       yyextra->specialBlock = FALSE; 
-                       //yyextra->hideClassDocs = FALSE;
-                      }
-    {NEWLINE}        
-                       yyextra->current->program << *yytext;
-                       incLineNr(yyscanner); 
-                     }
+                        yyextra->current->program << yytext;
+                        yyextra->specialBlock = FALSE;
+                        //yyextra->hideClassDocs = FALSE;
+                      }
+    {NEWLINE}         {
+                        yyextra->current->program << *yytext;
+                        incLineNr(yyscanner);
+                      }
     {POUNDCOMMENT}    { // normal comment
-                       yyextra->current->program << yytext;
+                        yyextra->current->program << yytext;
                       }
     .                 { // any character
-                       yyextra->specialBlock = FALSE; 
-                       yyextra->current->program << *yytext;
+                        yyextra->specialBlock = FALSE;
+                        yyextra->current->program << *yytext;
                       }
     {TRIDOUBLEQUOTE}  { // start of a comment block
-                       //if (!yyextra->hideClassDocs) 
-                       yyextra->current->program << yytext;
-                       initTriDoubleQuoteBlock(yyscanner);
-                       BEGIN(TripleComment);
+                        //if (!yyextra->hideClassDocs)
+                        yyextra->current->program << yytext;
+                        initTriDoubleQuoteBlock(yyscanner);
+                        BEGIN(TripleComment);
                       }
 
     {TRISINGLEQUOTE}  { // start of a comment block
-                       //if (!yyextra->hideClassDocs) 
-                       yyextra->current->program << yytext;
-                       initTriSingleQuoteBlock(yyscanner);
-                       BEGIN(TripleComment);
+                        //if (!yyextra->hideClassDocs)
+                        yyextra->current->program << yytext;
+                        initTriSingleQuoteBlock(yyscanner);
+                        BEGIN(TripleComment);
                       }
 }
 
 <ClassDec>{IDENTIFIER} {
-                         if (yyextra->current->type.isEmpty()) 
-                         {
-                             yyextra->current->type = "class";
-                         }
-
-                         yyextra->current->section = Entry::CLASS_SEC;
-                         yyextra->current->name = yytext;
-
-                         // prepend scope in case of nested classes
-                         if (yyextra->current_root->section&Entry::SCOPE_MASK)
-                         {
-                           //printf("*** Prepending scope %s to class %s\n",qPrint(yyextra->current_root->name),qPrint(yyextra->current->name));
-                           yyextra->current->name.prepend(yyextra->current_root->name+"::");
-                         }
-                         
-                         yyextra->current->name = yyextra->current->name.stripWhiteSpace();
-                         yyextra->current->fileName = yyextra->yyFileName;        
-                         yyextra->docBlockContext   = YY_START;
-                         yyextra->docBlockInBody    = FALSE;
-                         yyextra->docBlockJavaStyle = FALSE;
-                         yyextra->docBlock.resize(0);
-
-                         BEGIN(ClassInheritance);                 
+                          if (yyextra->current->type.isEmpty())
+                          {
+                              yyextra->current->type = "class";
+                          }
+
+                          yyextra->current->section = Entry::CLASS_SEC;
+                          yyextra->current->name = yytext;
+
+                          // prepend scope in case of nested classes
+                          if (yyextra->current_root->section&Entry::SCOPE_MASK)
+                          {
+                            //printf("*** Prepending scope %s to class %s\n",qPrint(yyextra->current_root->name),qPrint(yyextra->current->name));
+                            yyextra->current->name.prepend(yyextra->current_root->name+"::");
+                          }
+
+                          yyextra->current->name = yyextra->current->name.stripWhiteSpace();
+                          yyextra->current->fileName = yyextra->fileName;
+                          yyextra->docBlockContext   = YY_START;
+                          yyextra->docBlockInBody    = FALSE;
+                          yyextra->docBlockJavaStyle = FALSE;
+                          yyextra->docBlock.resize(0);
+
+                          BEGIN(ClassInheritance);
                         }
 
 <ClassInheritance>{
@@ -984,57 +1007,57 @@ STARTDOCSYMS      "##"
                        }
 
     ":"                { // begin of the class definition
-                        yyextra->specialBlock = TRUE; // expecting a docstring
+                         yyextra->specialBlock = TRUE; // expecting a docstring
                          yyextra->current->bodyLine  = yyextra->yyLineNr;
-                        yyextra->current->program.str(std::string());
-                        BEGIN(ClassCaptureIndent);
+                         yyextra->current->program.str(std::string());
+                         BEGIN(ClassCaptureIndent);
                        }
 
     {SCOPE}            {
                          yyextra->current->extends.push_back(
-                                             BaseInfo(substitute(yytext,".","::"),Public,Normal)
-                                           );
+                                              BaseInfo(substitute(yytext,".","::"),Public,Normal)
+                                            );
                          //Has base class-do stuff
                        }
-    "'"                       { // start of a single quoted string
-                                yyextra->stringContext=YY_START;
+    "'"                { // start of a single quoted string
+                         yyextra->stringContext=YY_START;
                          BEGIN( SingleQuoteStringIgnore );
                        }
     "\""               { // start of a double quoted string
-                                yyextra->stringContext=YY_START;
+                         yyextra->stringContext=YY_START;
                          BEGIN( DoubleQuoteStringIgnore );
                        }
 }
 
 <SingleQuoteStringIgnore>{
-    "'"                       { // end of a single quoted string
-                        BEGIN(yyextra->stringContext);
+    "'"                { // end of a single quoted string
+                         BEGIN(yyextra->stringContext);
                        }
-    .                 { }
+    .                  { }
 }
 <DoubleQuoteStringIgnore>{
-    "\""              { // end of a double quoted string
-                        BEGIN(yyextra->stringContext);
+    "\""               { // end of a double quoted string
+                         BEGIN(yyextra->stringContext);
                        }
-    .                 { }
+    .                  { }
 }
 
 <ClassCaptureIndent>{
     "\n"|({BB}"\n")            {
                                  // Blankline - ignore, keep looking for indentation.
-                                lineCount(yyscanner);
-                                yyextra->current->program << yytext;
+                                 lineCount(yyscanner);
+                                 yyextra->current->program << yytext;
                                }
 
     {TRIDOUBLEQUOTE}           { // start of a comment block
-                                initTriDoubleQuoteBlock(yyscanner);
-                                yyextra->current->program << yytext;
-                                BEGIN(TripleComment);
-                              }
+                                 initTriDoubleQuoteBlock(yyscanner);
+                                 yyextra->current->program << yytext;
+                                 BEGIN(TripleComment);
+                               }
     {TRISINGLEQUOTE}           { // start of a comment block
-                                initTriSingleQuoteBlock(yyscanner);
-                                yyextra->current->program << yytext;
-                                BEGIN(TripleComment);
+                                 initTriSingleQuoteBlock(yyscanner);
+                                 yyextra->current->program << yytext;
+                                 BEGIN(TripleComment);
                                }
     {STARTDOCSYMS}[#]*         {  // start of a special comment
                                  initSpecialBlock(yyscanner);
@@ -1042,25 +1065,25 @@ STARTDOCSYMS      "##"
                                }
     {POUNDCOMMENT}             { // ignore comment with just one #
                                }
-    ^{BB}                     {
-                                yyextra->current->program << yytext;
-                                //yyextra->current->startLine = yyextra->yyLineNr;
-                                yyextra->curIndent=computeIndent(yytext);
-                                yyextra->bodyEntry = yyextra->current;
-                                DBG_CTX((stderr,"setting indent %d\n",yyextra->curIndent));
-                                //printf("yyextra->current->program=[%s]\n",qPrint(yyextra->current->program));
-                                //yyextra->hideClassDocs = TRUE;
-                                BEGIN(ClassBody);
+    ^{BB}                      {
+                                 yyextra->current->program << yytext;
+                                 //yyextra->current->startLine = yyextra->yyLineNr;
+                                 yyextra->curIndent=computeIndent(yytext);
+                                 yyextra->bodyEntry = yyextra->current;
+                                 DBG_CTX((stderr,"setting indent %d\n",yyextra->curIndent));
+                                 //printf("yyextra->current->program=[%s]\n",qPrint(yyextra->current->program));
+                                 //yyextra->hideClassDocs = TRUE;
+                                 BEGIN(ClassBody);
                                }
 
     ""/({NONEMPTY}|{EXPCHAR})  {
-                                // Just pushback an empty class, and
-                                // resume parsing the body.
+                                 // Just pushback an empty class, and
+                                 // resume parsing the body.
                                  newEntry(yyscanner);
-                                yyextra->current->program << yytext;
+                                 yyextra->current->program << yytext;
 
-                                // printf("Failed to find indent - skipping!");
-                                BEGIN( Search );
+                                 // printf("Failed to find indent - skipping!");
+                                 BEGIN( Search );
                                }
 }
 
@@ -1069,88 +1092,88 @@ STARTDOCSYMS      "##"
    "="                { // the assignment operator
                         //printf("====== VariableDec at line %d\n",yyextra->yyLineNr);
                         yyextra->start_init = TRUE;
-                       yyextra->current->initializer.str(yytext);
-                       yyextra->current->initializer << " ";
+                        yyextra->current->initializer.str(yytext);
+                        yyextra->current->initializer << " ";
                       }
    {B}                { // spaces
-                       yyextra->current->initializer << yytext;
-                     }
-   {INTNUMBER}       { // integer value
-                       if (yyextra->current-> type.isEmpty()) yyextra->current->type = "int";
-                       yyextra->current->initializer << yytext;
-                     }
+                        yyextra->current->initializer << yytext;
+                      }
+   {INTNUMBER}        { // integer value
+                        if (yyextra->current-> type.isEmpty()) yyextra->current->type = "int";
+                        yyextra->current->initializer << yytext;
+                      }
    {FLOATNUMBER}      { // floating point value
-                       if (yyextra->current->type.isEmpty()) yyextra->current->type = "float";
-                       yyextra->current->initializer << yytext;
-                     }
+                        if (yyextra->current->type.isEmpty()) yyextra->current->type = "float";
+                        yyextra->current->initializer << yytext;
+                      }
    {BOOL}             { // boolean value
-                       if (yyextra->current->type.isEmpty()) yyextra->current->type = "bool";
-                       yyextra->current->initializer << yytext;
-                     }
+                        if (yyextra->current->type.isEmpty()) yyextra->current->type = "bool";
+                        yyextra->current->initializer << yytext;
+                      }
    {STRINGPREFIX}?"'" { // string
-                       if (yyextra->current->type.isEmpty()) yyextra->current->type = "string";
-                       yyextra->current->initializer << yytext;
-                       yyextra->copyString=&yyextra->current->initializer;
-                               yyextra->stringContext=VariableDec;
+                        if (yyextra->current->type.isEmpty()) yyextra->current->type = "string";
+                        yyextra->current->initializer << yytext;
+                        yyextra->copyString=&yyextra->current->initializer;
+                        yyextra->stringContext=VariableDec;
                         BEGIN( SingleQuoteString );
-                     }
+                      }
    {STRINGPREFIX}?"\"" { // string
-                       if (yyextra->current->type.isEmpty()) yyextra->current->type = "string";
-                       yyextra->current->initializer << yytext;
-                       yyextra->copyString=&yyextra->current->initializer;
-                               yyextra->stringContext=VariableDec;
+                        if (yyextra->current->type.isEmpty()) yyextra->current->type = "string";
+                        yyextra->current->initializer << yytext;
+                        yyextra->copyString=&yyextra->current->initializer;
+                        yyextra->stringContext=VariableDec;
                         BEGIN( DoubleQuoteString );
-                     }
+                      }
    {TRIDOUBLEQUOTE}   { // start of a comment block
-                       if (yyextra->current->type.isEmpty()) yyextra->current->type = "string";
-                       yyextra->current->initializer << yytext;
-                       yyextra->doubleQuote=TRUE;
-                       yyextra->copyString=&yyextra->current->initializer;
-                               yyextra->stringContext=VariableDec;
-                       BEGIN(TripleString);
+                        if (yyextra->current->type.isEmpty()) yyextra->current->type = "string";
+                        yyextra->current->initializer << yytext;
+                        yyextra->doubleQuote=TRUE;
+                        yyextra->copyString=&yyextra->current->initializer;
+                        yyextra->stringContext=VariableDec;
+                        BEGIN(TripleString);
                       }
 
    {TRISINGLEQUOTE}   { // start of a comment block
-                       if (yyextra->current->type.isEmpty()) yyextra->current->type = "string";
-                       yyextra->current->initializer << yytext;
-                       yyextra->doubleQuote=FALSE;
-                       yyextra->copyString=&yyextra->current->initializer;
-                               yyextra->stringContext=VariableDec;
-                       BEGIN(TripleString);
-                      }
-   "("               { // tuple, only when direct after =
+                        if (yyextra->current->type.isEmpty()) yyextra->current->type = "string";
+                        yyextra->current->initializer << yytext;
+                        yyextra->doubleQuote=FALSE;
+                        yyextra->copyString=&yyextra->current->initializer;
+                        yyextra->stringContext=VariableDec;
+                        BEGIN(TripleString);
+                      }
+   "("                { // tuple, only when direct after =
                         if (yyextra->current->mtype!=Property && yyextra->start_init)
-                       {
-                         yyextra->current->type = "tuple";
-                       }
-                       yyextra->current->initializer << *yytext;
+                        {
+                          yyextra->current->type = "tuple";
+                        }
+                        yyextra->current->initializer << *yytext;
                         yyextra->atomStart='(';
-                       yyextra->atomEnd=')';
-                       yyextra->atomCount=1;
-                       BEGIN( VariableAtom );
+                        yyextra->atomEnd=')';
+                        yyextra->atomCount=1;
+                        BEGIN( VariableAtom );
                       }
    "["                { // list
                         if (yyextra->start_init) yyextra->current->type = "list";
-                       yyextra->current->initializer << *yytext;
+                        yyextra->current->initializer << *yytext;
                         yyextra->atomStart='[';
-                       yyextra->atomEnd=']';
-                       yyextra->atomCount=1;
-                       BEGIN( VariableAtom );
+                        yyextra->atomEnd=']';
+                        yyextra->atomCount=1;
+                        BEGIN( VariableAtom );
                       }
-   "{"               { // dictionary
+   "{"                { // dictionary
                         if (yyextra->start_init) yyextra->current->type = "dictionary";
-                       yyextra->current->initializer << *yytext;
+                        yyextra->current->initializer << *yytext;
                         yyextra->atomStart='{';
-                       yyextra->atomEnd='}';
-                       yyextra->atomCount=1;
-                       BEGIN( VariableAtom );
+                        yyextra->atomEnd='}';
+                        yyextra->atomCount=1;
+                        BEGIN( VariableAtom );
                       }
    "#".*              { // comment
-                        BEGIN( VariableEnd ); 
+                        BEGIN( VariableEnd );
                       }
-   {IDENTIFIER}              {
-                       // do something based on the type of the IDENTIFIER
-                       if (yyextra->current->type.isEmpty())
+   {IDENTIFIER}       {
+                        // do something based on the type of the IDENTIFIER
+                        if (yyextra->current->type.isEmpty())
                         {
                           for (const auto &child : yyextra->current_root->children())
                           {
@@ -1162,270 +1185,277 @@ STARTDOCSYMS      "##"
                           }
                         }
                         yyextra->start_init = FALSE;
-                       yyextra->current->initializer << yytext;
-                     }
-   .                 {
+                        yyextra->current->initializer << yytext;
+                      }
+   .                  {
                         yyextra->start_init = FALSE;
-                       yyextra->current->initializer << *yytext;
+                        yyextra->current->initializer << *yytext;
+                      }
+   \n                 {
+                        unput('\n');
+                        BEGIN( VariableEnd );
                       }
-   \n                {
-                       unput('\n');
-                       BEGIN( VariableEnd );
-                     }
 }
 
 <VariableAtom>{
-    [\(\[\{]         {
-                       yyextra->current->initializer << *yytext;
+    [\(\[\{]          {
+                        yyextra->current->initializer << *yytext;
                         if (yyextra->atomStart==*yytext)
-                       {
-                         yyextra->atomCount++;
-                       }
+                        {
+                          yyextra->atomCount++;
+                        }
                       }
-    [\)\]\}]         {
-                       yyextra->current->initializer << *yytext;
+    [\)\]\}]          {
+                        yyextra->current->initializer << *yytext;
                         if (yyextra->atomEnd==*yytext)
-                       {
-                         yyextra->atomCount--;
-                       }
-                       if (yyextra->atomCount==0)
-                       {
+                        {
+                          yyextra->atomCount--;
+                        }
+                        if (yyextra->atomCount==0)
+                        {
                           yyextra->start_init = FALSE;
-                         BEGIN(VariableDec);
-                       }
+                          BEGIN(VariableDec);
+                        }
                       }
     {TRIDOUBLEQUOTE}  { // start of a comment block
                         yyextra->specialBlock = FALSE;
-                       yyextra->current->program << yytext;
-                       initTriDoubleQuoteBlock(yyscanner);
-                       BEGIN(TripleComment);
+                        yyextra->current->program << yytext;
+                        initTriDoubleQuoteBlock(yyscanner);
+                        BEGIN(TripleComment);
                       }
 
     {TRISINGLEQUOTE}  { // start of a comment block
                         yyextra->specialBlock = FALSE;
-                       yyextra->current->program << yytext;
-                       initTriSingleQuoteBlock(yyscanner);
-                       BEGIN(TripleComment);
-                      }
-   "'"               {
-                               yyextra->stringContext=YY_START;
-                       yyextra->current->initializer << "'";
-                       yyextra->copyString=&yyextra->current->initializer;
+                        yyextra->current->program << yytext;
+                        initTriSingleQuoteBlock(yyscanner);
+                        BEGIN(TripleComment);
+                      }
+   "'"                {
+                        yyextra->stringContext=YY_START;
+                        yyextra->current->initializer << "'";
+                        yyextra->copyString=&yyextra->current->initializer;
                         BEGIN( SingleQuoteString );
                       }
-   "\""                      {
-                               yyextra->stringContext=YY_START;
-                       yyextra->current->initializer << "\"";
-                       yyextra->copyString=&yyextra->current->initializer;
+   "\""               {
+                        yyextra->stringContext=YY_START;
+                        yyextra->current->initializer << "\"";
+                        yyextra->copyString=&yyextra->current->initializer;
                         BEGIN( DoubleQuoteString );
                       }
    {IDENTIFIER}       {
-                       yyextra->current->initializer << yytext;
-                     }
-   .                 {
-                       yyextra->current->initializer << *yytext;
+                        yyextra->current->initializer << yytext;
+                      }
+   .                  {
+                        yyextra->current->initializer << *yytext;
+                      }
+   \n                 {
+                        yyextra->current->initializer << *yytext;
+                        incLineNr(yyscanner);
                       }
-   \n                {
-                       yyextra->current->initializer << *yytext;
-                       incLineNr(yyscanner);
-                     }
 
 }
 
 <VariableEnd>{
     \n                {
                         incLineNr(yyscanner);
-                       newVariable(yyscanner);
+                        newVariable(yyscanner);
                         BEGIN(Search);
                       }
-    .                
+    .                 {
                         unput(*yytext);
-                       newVariable(yyscanner);
+                        newVariable(yyscanner);
                         BEGIN(Search);
-                     }
+                      }
     <<EOF>>           { yyterminate();
                       }
 }
 
 <TripleComment>{
-    {ENDTRIDOUBLEQUOTE}   | 
+    {ENDTRIDOUBLEQUOTE}   |
     {ENDTRISINGLEQUOTE}   {
-                         // printf("Expected module block %d special=%d\n",yyextra->expectModuleDocs,yyextra->specialBlock);
-                         if (yyextra->doubleQuote==(yytext[0]=='"')) 
-                         {
-                           if (yyextra->specialBlock) // expecting a docstring
-                           {
-                             QCString actualDoc=yyextra->docBlock;
-                             if (!yyextra->docBlockSpecial) // legacy unformatted docstring
-                             {
+                          // printf("Expected module block %d special=%d\n",yyextra->expectModuleDocs,yyextra->specialBlock);
+                          if (yyextra->doubleQuote==(yytext[0]=='"'))
+                          {
+                            if (yyextra->specialBlock) // expecting a docstring
+                            {
+                              QCString actualDoc=yyextra->docBlock;
+                              if (!yyextra->docBlockSpecial) // legacy unformatted docstring
+                              {
                                 if (!actualDoc.isEmpty())
                                 {
                                   stripIndentation(actualDoc,yyextra->commentIndent);
-                                 actualDoc.prepend("\\verbatim\n");
-                                 actualDoc.append("\\endverbatim ");
-                               }
-                             }
-                             //printf("-------> yyextra->current=%p yyextra->bodyEntry=%p\n",yyextra->current,yyextra->bodyEntry);
-                             handleCommentBlock(yyscanner, actualDoc, FALSE);
-                           }
-                           else if (yyextra->packageCommentAllowed) // expecting module docs
-                           {
-                             QCString actualDoc=yyextra->docBlock;
-                             if (!yyextra->docBlockSpecial) // legacy unformatted docstring
-                             {
+                                  actualDoc.prepend("\\verbatim\n");
+                                  actualDoc.append("\\endverbatim ");
+                                }
+                              }
+                              //printf("-------> yyextra->current=%p yyextra->bodyEntry=%p\n",yyextra->current,yyextra->bodyEntry);
+                              handleCommentBlock(yyscanner, actualDoc, FALSE);
+                            }
+                            else if (yyextra->packageCommentAllowed) // expecting module docs
+                            {
+                              QCString actualDoc=yyextra->docBlock;
+                              if (!yyextra->docBlockSpecial) // legacy unformatted docstring
+                              {
                                 if (!actualDoc.isEmpty())
                                 {
                                   stripIndentation(actualDoc,yyextra->commentIndent);
-                                 actualDoc.prepend("\\verbatim\n");
-                                 actualDoc.append("\\endverbatim ");
-                               }
-                             }
-                             actualDoc.prepend("\\namespace "+yyextra->moduleScope+" ");
-                             handleCommentBlock(yyscanner, actualDoc, FALSE);
-                           }
-                           if ((yyextra->docBlockContext==ClassBody /*&& !yyextra->hideClassDocs*/) ||
-                               yyextra->docBlockContext==FunctionBody)
-                           {
-                             yyextra->current->program << yyextra->docBlock;
-                             yyextra->current->program << yytext;
-                           }
+                                  actualDoc.prepend("\\verbatim\n");
+                                  actualDoc.append("\\endverbatim ");
+                                }
+                              }
+                              if (yyextra->moduleScope.startsWith("__") &&  yyextra->moduleScope.endsWith("__"))
+                              {
+                                actualDoc.prepend("\\namespace \\"+yyextra->moduleScope+" ");
+                              }
+                              else
+                              {
+                                actualDoc.prepend("\\namespace "+yyextra->moduleScope+" ");
+                              }
+                              handleCommentBlock(yyscanner, actualDoc, FALSE);
+                            }
+                            if ((yyextra->docBlockContext==ClassBody /*&& !yyextra->hideClassDocs*/) ||
+                                yyextra->docBlockContext==FunctionBody)
+                            {
+                              yyextra->current->program << yyextra->docBlock;
+                              yyextra->current->program << yytext;
+                            }
                             //if (yyextra->hideClassDocs)
-                           //{
+                            //{
                             //  yyextra->current->startLine = yyextra->yyLineNr;
-                           //}
-                           //yyextra->hideClassDocs=FALSE;
-                           BEGIN(yyextra->docBlockContext);
-                         }
-                          else 
-                         {
+                            //}
+                            //yyextra->hideClassDocs=FALSE;
+                            BEGIN(yyextra->docBlockContext);
+                          }
+                          else
+                          {
                             yyextra->docBlock += yytext;
                           }
-                         yyextra->packageCommentAllowed = FALSE;
+                          yyextra->packageCommentAllowed = FALSE;
                         }
 
 
-    ^{BB}              { // leading whitespace
-                         yyextra->docBlock += yytext;
-                       }
+    ^{BB}               { // leading whitespace
+                          yyextra->docBlock += yytext;
+                        }
     [^"'\n \t\\]+       {
-                         yyextra->docBlock += yytext;
-                        }
-    \n                 {
-                         incLineNr(yyscanner);
-                         yyextra->docBlock += yytext;
-                       }
-    \\.                        { // escaped char
-                         yyextra->docBlock += yytext;
-                       }
-    .                  {
-                         yyextra->docBlock += yytext;
-                       }
+                          yyextra->docBlock += yytext;
+                        }
+    \n                  {
+                          incLineNr(yyscanner);
+                          yyextra->docBlock += yytext;
+                        }
+    \\.                 { // escaped char
+                          yyextra->docBlock += yytext;
+                        }
+    .                   {
+                          yyextra->docBlock += yytext;
+                        }
 }
 
 <SpecialComment>{
-    ^{B}"#"("#")*      { // skip leading hashes
-                       }
-    \n/{B}"#"          { // continuation of the comment on the next line
-                         yyextra->docBlock+='\n';
-                         yyextra->docBrief = FALSE;
-                         incLineNr(yyscanner);
-                       }
+    ^{B}"#"("#")*       { // skip leading hashes
+                        }
+    \n/{B}"#"           { // continuation of the comment on the next line
+                          yyextra->docBlock+='\n';
+                          yyextra->docBrief = FALSE;
+                          incLineNr(yyscanner);
+                        }
     [^#\n]+             { // any other stuff
-                         yyextra->docBlock+=yytext;
-                       }
-    \n                 { // new line that ends the comment
-                         handleCommentBlock(yyscanner, yyextra->docBlock, yyextra->docBrief);
-                         incLineNr(yyscanner);
-                         BEGIN(yyextra->docBlockContext);
-                       }
-    .                  { // anything we missed
-                         yyextra->docBlock+=*yytext;
-                       }
+                          yyextra->docBlock+=yytext;
+                        }
+    \n                  { // new line that ends the comment
+                          handleCommentBlock(yyscanner, yyextra->docBlock, yyextra->docBrief);
+                          incLineNr(yyscanner);
+                          BEGIN(yyextra->docBlockContext);
+                        }
+    .                   { // anything we missed
+                          yyextra->docBlock+=*yytext;
+                        }
 }
 
 <SingleQuoteString>{
     \\{B}\n                    { // line continuation
-                                addToString(yyscanner,yytext);
-                                incLineNr(yyscanner);
+                                 addToString(yyscanner,yytext);
+                                 incLineNr(yyscanner);
                                }
-    \\.                               { // escaped char
-                                addToString(yyscanner,yytext);
+    \\.                        { // escaped char
+                                 addToString(yyscanner,yytext);
                                }
-    "\"\"\""                  { // triple double quotes
-                                addToString(yyscanner,yytext);
-                              }
-    "'"                               { // end of the string
-                                addToString(yyscanner,yytext);
-                                BEGIN(yyextra->stringContext);
+    "\"\"\""                   { // triple double quotes
+                                 addToString(yyscanner,yytext);
                                }
-    [^"'\n\\]+                { // normal chars
-                                addToString(yyscanner,yytext);
+    "'"                        { // end of the string
+                                 addToString(yyscanner,yytext);
+                                 BEGIN(yyextra->stringContext);
                                }
-    .                         { // normal char
-                                addToString(yyscanner,yytext);
+    [^"'\n\\]+                 { // normal chars
+                                 addToString(yyscanner,yytext);
+                               }
+    .                          { // normal char
+                                 addToString(yyscanner,yytext);
                                }
 }
 
 <DoubleQuoteString>{
     \\{B}\n                    { // line continuation
-                                addToString(yyscanner,yytext);
-                                incLineNr(yyscanner);
+                                 addToString(yyscanner,yytext);
+                                 incLineNr(yyscanner);
+                               }
+    \\.                        { // escaped char
+                                 addToString(yyscanner,yytext);
                                }
-    \\.                               { // escaped char
-                                addToString(yyscanner,yytext);
+    "'''"                      { // triple single quotes
+                                 addToString(yyscanner,yytext);
                                }
-    "'''"                     { // triple single quotes
-                                addToString(yyscanner,yytext);
-                              }
-    "\""                      { // end of the string
-                                addToString(yyscanner,yytext);
-                                BEGIN(yyextra->stringContext);
+    "\""                       { // end of the string
+                                 addToString(yyscanner,yytext);
+                                 BEGIN(yyextra->stringContext);
                                }
-    [^"'\n\\]+                { // normal chars
-                                addToString(yyscanner,yytext);
+    [^"'\n\\]+                 { // normal chars
+                                 addToString(yyscanner,yytext);
                                }
-    .                         { // normal char
-                                addToString(yyscanner,yytext);
+    .                          { // normal char
+                                 addToString(yyscanner,yytext);
                                }
 }
 
 <TripleString>{
-    {ENDTRIDOUBLEQUOTE}    | 
+    {ENDTRIDOUBLEQUOTE}    |
     {ENDTRISINGLEQUOTE}    {
                           *yyextra->copyString << yytext;
-                         if (yyextra->doubleQuote==(yytext[0]=='"')) 
-                         {
-                           BEGIN(yyextra->stringContext);
-                         }
+                          if (yyextra->doubleQuote==(yytext[0]=='"'))
+                          {
+                            BEGIN(yyextra->stringContext);
+                          }
                         }
 
 
     ({LONGSTRINGBLOCK}) {
-                         lineCount(yyscanner);
+                          lineCount(yyscanner);
                           *yyextra->copyString << yytext;
                         }
-    \n                 {
-                         incLineNr(yyscanner);
+    \n                  {
+                          incLineNr(yyscanner);
                           *yyextra->copyString << yytext;
-                       }
-    .                  {
+                        }
+    .                   {
                           *yyextra->copyString << *yytext;
-                       }
+                        }
 }
 
   /* ------------ End rules -------------- */
 
   /*
 <*>({NONEMPTY}|{EXPCHAR}|{BB})           { // This should go one character at a time.
-                                // printf("[pyscanner] '%s' [ state %d ]  [line %d] no match\n",
-                                //       yytext, YY_START, yyextra->yyLineNr);
+                                 // printf("[pyscanner] '%s' [ state %d ]  [line %d] no match\n",
+                                 //       yytext, YY_START, yyextra->yyLineNr);
 
                                }
   */
 
 <*>{NEWLINE}                   {
-                                //printf("[pyscanner] %d NEWLINE [line %d] no match\n",
-                                //       YY_START, yyextra->yyLineNr);
+                                 //printf("[pyscanner] %d NEWLINE [line %d] no match\n",
+                                 //       YY_START, yyextra->yyLineNr);
 
                                  lineCount(yyscanner);
                                }
@@ -1435,8 +1465,8 @@ STARTDOCSYMS      "##"
                                }
 
 <*>.                           {
-                                //printf("[pyscanner] '%s' [ state %d ]  [line %d] no match\n",
-                                //       yytext, YY_START, yyextra->yyLineNr);
+                                 //printf("[pyscanner] '%s' [ state %d ]  [line %d] no match\n",
+                                 //       yytext, YY_START, yyextra->yyLineNr);
 
                                }
 
@@ -1474,7 +1504,7 @@ static void initEntry(yyscan_t yyscanner)
   yyextra->current->mtype      = yyextra->mtype;
   yyextra->current->virt       = yyextra->virt;
   yyextra->current->stat       = yyextra->stat;
-  yyextra->current->lang       = SrcLangExt_Python; 
+  yyextra->current->lang       = SrcLangExt_Python;
   yyextra->commentScanner.initGroupInfo(yyextra->current.get());
   yyextra->stat = FALSE;
 }
@@ -1548,7 +1578,7 @@ static QCString findPackageScopeFromPath(yyscan_t yyscanner,const QCString &path
       QCString scope = findPackageScopeFromPath(yyscanner,path.left(i));
       if (!scope.isEmpty())
       {
-       scope+="::";
+        scope+="::";
       }
       scope+=path.mid(i+1);
       yyextra->packageNameCache.insert(std::make_pair(path.str(),scope.str()));
@@ -1570,8 +1600,8 @@ static void addFrom(yyscan_t yyscanner,bool all)
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   QCString item=all ? yyextra->packageName : yyextra->packageName+"."+yytext;
   yyextra->current->name=removeRedundantWhiteSpace(substitute(item,".","::"));
-  yyextra->current->fileName = yyextra->yyFileName; 
-  //printf("Adding using declaration: found:%s:%d name=%s\n",qPrint(yyextra->yyFileName),yyextra->yyLineNr,qPrint(yyextra->current->name));
+  yyextra->current->fileName = yyextra->fileName;
+  //printf("Adding using declaration: found:%s:%d name=%s\n",qPrint(yyextra->fileName),yyextra->yyLineNr,qPrint(yyextra->current->name));
   yyextra->current->section=all ? Entry::USINGDIR_SEC : Entry::USINGDECL_SEC;
   yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
   initEntry(yyscanner);
@@ -1601,12 +1631,12 @@ static void startCommentBlock(yyscan_t yyscanner,bool brief)
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   if (brief)
   {
-    yyextra->current->briefFile = yyextra->yyFileName;
+    yyextra->current->briefFile = yyextra->fileName;
     yyextra->current->briefLine = yyextra->yyLineNr;
   }
   else
   {
-    yyextra->current->docFile = yyextra->yyFileName;
+    yyextra->current->docFile = yyextra->fileName;
     yyextra->current->docLine = yyextra->yyLineNr;
   }
 }
@@ -1619,7 +1649,7 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief
 
   // TODO: Fix me
   yyextra->docBlockInBody=FALSE;
-  
+
   if (!yyextra->current->doc.isEmpty())
   {
     yyextra->current->doc=yyextra->current->doc.stripWhiteSpace()+"\n\n";
@@ -1632,15 +1662,15 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief
   int position = 0;
   bool needsEntry = false;
   int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine;
-  Markdown markdown(yyextra->yyFileName,lineNr);
+  Markdown markdown(yyextra->fileName,lineNr);
   QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(doc,lineNr) : doc;
   while (yyextra->commentScanner.parseCommentBlock(
         yyextra->thisParser,
         (yyextra->docBlockInBody && yyextra->previous) ? yyextra->previous.get() : yyextra->current.get(),
         processedDoc, // text
-        yyextra->yyFileName,   // file
+        yyextra->fileName,   // file
         lineNr,
-        yyextra->docBlockInBody ? FALSE : brief, 
+        yyextra->docBlockInBody ? FALSE : brief,
         yyextra->docBlockJavaStyle, // javadoc style // or FALSE,
         yyextra->docBlockInBody,
         yyextra->protection,
@@ -1721,7 +1751,7 @@ static void initSpecialBlock(yyscan_t yyscanner)
 static void searchFoundDef(yyscan_t yyscanner)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
-  yyextra->current->fileName  = yyextra->yyFileName;
+  yyextra->current->fileName  = yyextra->fileName;
   yyextra->current->startLine = yyextra->yyLineNr;
   yyextra->current->bodyLine  = yyextra->yyLineNr;
   yyextra->current->section = Entry::FUNCTION_SEC;
@@ -1744,7 +1774,7 @@ static void searchFoundClass(yyscan_t yyscanner)
   yyextra->current->section = Entry::CLASS_SEC;
   yyextra->current->argList.clear();
   yyextra->current->type += "class" ;
-  yyextra->current->fileName  = yyextra->yyFileName;
+  yyextra->current->fileName  = yyextra->fileName;
   yyextra->current->startLine  = yyextra->yyLineNr;
   yyextra->current->bodyLine  = yyextra->yyLineNr;
   yyextra->packageCommentAllowed = FALSE;
@@ -1776,17 +1806,17 @@ static void parseCompounds(yyscan_t yyscanner,std::shared_ptr<Entry> rt)
       else if (ce->parent())
       {
         yyextra->current_root = rt;
-       //printf("Searching for member variables in %s parent=%s\n",
-       //    qPrint(ce->name),qPrint(ce->parent->name));
-       BEGIN( SearchMemVars );
+        //printf("Searching for member variables in %s parent=%s\n",
+        //    qPrint(ce->name),qPrint(ce->parent->name));
+        BEGIN( SearchMemVars );
       }
-      yyextra->yyFileName = ce->fileName;
+      yyextra->fileName = ce->fileName;
       yyextra->yyLineNr   = ce->bodyLine ;
       yyextra->current = std::make_shared<Entry>();
       initEntry(yyscanner);
 
       QCString name = ce->name;
-      yyextra->commentScanner.enterCompound(yyextra->yyFileName,yyextra->yyLineNr,name);
+      yyextra->commentScanner.enterCompound(yyextra->fileName,yyextra->yyLineNr,name);
 
       pyscannerYYlex(yyscanner) ;
       yyextra->lexInit=TRUE;
@@ -1794,7 +1824,7 @@ static void parseCompounds(yyscan_t yyscanner,std::shared_ptr<Entry> rt)
       yyextra->programStr.resize(0);
       ce->program.str(std::string());
 
-      yyextra->commentScanner.leaveCompound(yyextra->yyFileName,yyextra->yyLineNr,name);
+      yyextra->commentScanner.leaveCompound(yyextra->fileName,yyextra->yyLineNr,name);
 
     }
     parseCompounds(yyscanner,ce);
@@ -1821,10 +1851,10 @@ static void parseMain(yyscan_t yyscanner, const QCString &fileName,const char *f
   yyextra->current_root  = rt;
   yyextra->specialBlock = FALSE;
 
-  yyextra->yyLineNr= 1 ; 
-  yyextra->yyFileName = fileName;
+  yyextra->yyLineNr= 1 ;
+  yyextra->fileName = fileName;
   //setContext();
-  msg("Parsing file %s...\n",qPrint(yyextra->yyFileName));
+  msg("Parsing file %s...\n",qPrint(yyextra->fileName));
 
   FileInfo fi(fileName.str());
   yyextra->moduleScope = findPackageScope(yyscanner,fileName);
@@ -1852,7 +1882,7 @@ static void parseMain(yyscan_t yyscanner, const QCString &fileName,const char *f
     yyextra->current->name      = scope.left(pos);
     yyextra->current->section   = Entry::NAMESPACE_SEC;
     yyextra->current->type      = "namespace";
-    yyextra->current->fileName  = yyextra->yyFileName;
+    yyextra->current->fileName  = yyextra->fileName;
     yyextra->current->startLine = yyextra->yyLineNr;
     yyextra->current->bodyLine  = yyextra->yyLineNr;
     yyextra->current_root       = yyextra->current;
@@ -1861,7 +1891,7 @@ static void parseMain(yyscan_t yyscanner, const QCString &fileName,const char *f
 
   initParser(yyscanner);
 
-  yyextra->commentScanner.enterFile(yyextra->yyFileName,yyextra->yyLineNr);
+  yyextra->commentScanner.enterFile(yyextra->fileName,yyextra->yyLineNr);
 
   yyextra->current->reset();
   initEntry(yyscanner);
@@ -1870,7 +1900,7 @@ static void parseMain(yyscan_t yyscanner, const QCString &fileName,const char *f
   pyscannerYYlex(yyscanner);
   yyextra->lexInit=TRUE;
 
-  yyextra->commentScanner.leaveFile(yyextra->yyFileName,yyextra->yyLineNr);
+  yyextra->commentScanner.leaveFile(yyextra->fileName,yyextra->yyLineNr);
 
   yyextra->programStr.resize(0);
   yyextra->current_root->program.str(std::string());
@@ -1884,9 +1914,9 @@ static void parsePrototype(yyscan_t yyscanner,const QCString &text)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   //printf("**** parsePrototype(%s) begin\n",qPrint(text));
-  if (text.isEmpty()) 
+  if (text.isEmpty())
   {
-    warn(yyextra->yyFileName,yyextra->yyLineNr,"Empty prototype found!");
+    warn(yyextra->fileName,yyextra->yyLineNr,"Empty prototype found!");
     return;
   }
 
@@ -1896,11 +1926,11 @@ static void parsePrototype(yyscan_t yyscanner,const QCString &text)
   const char *orgInputString;
   yy_size_t orgInputPosition;
   YY_BUFFER_STATE orgState;
-  
+
   // save scanner state
   orgState = YY_CURRENT_BUFFER;
   yy_switch_to_buffer(yy_create_buffer(0, YY_BUF_SIZE, yyscanner), yyscanner);
-  orgInputString = yyextra->inputString; 
+  orgInputString = yyextra->inputString;
   orgInputPosition = yyextra->inputPosition;
 
   // set new string
@@ -1922,7 +1952,7 @@ static void parsePrototype(yyscan_t yyscanner,const QCString &text)
   yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner);
   yy_switch_to_buffer(orgState, yyscanner);
 
-  yyextra->inputString = orgInputString; 
+  yyextra->inputString = orgInputString;
   yyextra->inputPosition = orgInputPosition;
 
   //printf("**** parsePrototype end\n");
index b8eb3e6..6d3d198 100644 (file)
@@ -251,6 +251,32 @@ class QCString
       return QCString(m_rep.substr(start,1+end-start));
     }
 
+    // Returns a quoted copy of this string, unless it is already quoted.
+    // Note that trailing and leading whitespace is removed.
+    QCString quoted() const
+    {
+      size_t start=0, sl=m_rep.size(), end=sl-1;
+      while (start<sl  && qisspace(m_rep[start])) start++; // skip over leading whitespace
+      if (start==sl) return QCString(); // only whitespace
+      while (end>start && qisspace(m_rep[end]))   end--;   // skip over trailing whitespace
+      bool needsQuotes=false;
+      size_t i=start;
+      if (i<end && m_rep[i]!='"') // stripped string has at least non-whitespace unquoted character
+      {
+        while (i<end && !needsQuotes) // check if the to be quoted part has at least one whitespace character
+        {
+          needsQuotes = qisspace(m_rep[i++]);
+        }
+      }
+      QCString result(m_rep.substr(start,1+end-start));
+      if (needsQuotes)
+      {
+        result.prepend("\"");
+        result.append("\"");
+      }
+      return result;
+    }
+
     /// returns a copy of this string with all whitespace removed
     QCString removeWhiteSpace() const
     {
index fc2f215..cac54d3 100644 (file)
@@ -38,7 +38,7 @@ static QCString makeFileName(const QCString & withoutExtension)
     }
     else // add specified HTML extension
     {
-      result+=Doxygen::htmlFileExtension;
+      addHtmlExtensionIfMissing(result);
     }
   }
   return result;
@@ -53,7 +53,7 @@ static QCString makeRef(const QCString & withoutExtension, const QCString & anch
   return result+"#"+anchor;
 }
 
-Qhp::Qhp() : m_prevSectionLevel(0), m_sectionLevel(0), m_skipMainPageSection(FALSE)
+Qhp::Qhp()
 {
   m_doc.setIndentLevel(0);
   m_toc.setIndentLevel(2);
@@ -136,6 +136,7 @@ void Qhp::initialize()
     NULL
   };
   m_toc.open("section", attributes);
+  m_openCount=1;
   m_prevSectionTitle = getFullProjectName();
   m_prevSectionLevel = 1;
   m_sectionLevel = 1;
@@ -148,9 +149,10 @@ void Qhp::finalize()
 {
   // Finish TOC
   handlePrevSection();
-  for (int i = m_prevSectionLevel; i > 0; i--)
+  while (m_openCount>0)
   {
     m_toc.close("section");
+    m_openCount--;
   }
   m_toc.close("toc");
   m_doc.insert(m_toc);
@@ -210,9 +212,11 @@ void Qhp::addContentsItem(bool /*isDir*/, const QCString & name,
 
   // Close sections as needed
   //printf("Qhp::addContentsItem() closing %d sections\n",diff);
-  for (; diff > 0; diff--)
+  while (diff>0)
   {
     m_toc.close("section");
+    m_openCount--;
+    diff--;
   }
 }
 
@@ -223,7 +227,7 @@ void Qhp::addIndexItem(const Definition *context,const MemberDef *md,
   //printf("addIndexItem(%s %s %s\n",
   //       context?context->name().data():"<none>",
   //       md?md->name().data():"<none>",
-  //       word);
+  //       qPrint(word));
 
   if (md) // member
   {
@@ -326,6 +330,7 @@ void Qhp::handlePrevSection()
     {
       // Section with children
       m_toc.open("section", attributes);
+      m_openCount++;
     }
     else
     {
index d1fc335..c35b632 100644 (file)
--- a/src/qhp.h
+++ b/src/qhp.h
@@ -61,10 +61,10 @@ class Qhp : public IndexIntf
     QCString m_prevSectionBaseName;
     QCString m_prevSectionAnchor;
 
-    int m_prevSectionLevel;
-    int m_sectionLevel;
-
-    bool m_skipMainPageSection;
+    int m_prevSectionLevel = 0;
+    int m_sectionLevel = 0;
+    int m_openCount = 0;
+    bool m_skipMainPageSection = false;
 };
 
 #endif // DOXYGEN_QHP_H
index 9a32449..ffa6128 100644 (file)
@@ -75,8 +75,8 @@ void RefList::generatePage()
       if (!first)
       {
         doc += "</dd>";
-        first=false;
       }
+      first=false;
       doc += " <dt>";
       doc += "\n";
       if (item->scope())
index 2a39f63..6286b0b 100644 (file)
@@ -178,7 +178,8 @@ class Ex::Private
 #if ENABLE_DEBUG
     void dump();
 #endif
-    bool matchAt(size_t tokenPos,const std::string &str,Match &match,size_t pos,int level) const;
+    bool matchAt(size_t tokenPos,size_t tokenLen,const std::string &str,
+                 Match &match,size_t pos,int level) const;
 
     /** Flag indicating the expression was successfully compiled */
     bool error = false;
@@ -377,6 +378,14 @@ void Ex::Private::compile()
             prevTokenPos+=ddiff;
             tokenPos+=ddiff;
           }
+          if (data[prevTokenPos].kind()==PToken::Kind::EndCapture)
+          {
+            // find the beginning of the capture range
+            while (prevTokenPos>0 && data[prevTokenPos].kind()!=PToken::Kind::BeginCapture)
+            {
+              prevTokenPos--;
+            }
+          }
           data.insert(data.begin()+prevTokenPos,
                       c=='?' ? PToken(PToken::Kind::Optional) : PToken(PToken::Kind::Star));
           tokenPos++;
@@ -430,14 +439,15 @@ void Ex::Private::dump()
 
 /** Internal matching routine.
  *  @param tokenPos Offset into the token stream.
+ *  @param tokenLen The length of the token stream.
  *  @param str      The input string to match against.
  *  @param match    The object used to store the matching results.
  *  @param pos      The position in the input string to start with matching
  *  @param level    Recursion level (used for debugging)
  */
-bool Ex::Private::matchAt(size_t tokenPos,const std::string &str,Match &match,const size_t pos,int level) const
+bool Ex::Private::matchAt(size_t tokenPos,size_t tokenLen,const std::string &str,Match &match,const size_t pos,int level) const
 {
-  DBG("%d:matchAt(tokenPos=%zu, str='%s', pos=%zu)\n",level,tokenPos,str.c_str(),pos);
+  DBG("%d:matchAt(tokenPos=%zu, str='%s', pos=%zu)\n",level,tokenPos,pos<str.length() ? str.substr(pos).c_str() : "",pos);
   auto isStartIdChar = [](char c) { return isalpha(c) || c=='_'; };
   auto isIdChar      = [](char c) { return isalnum(c) || c=='_'; };
   auto matchCharClass = [this,isStartIdChar,isIdChar](size_t tp,char c) -> bool
@@ -473,8 +483,8 @@ bool Ex::Private::matchAt(size_t tokenPos,const std::string &str,Match &match,co
     return negate ? !found : found;
   };
   size_t index = pos;
-  enum SequenceType { Star, Optional };
-  auto processSequence = [this,&tokenPos,&index,&str,&matchCharClass,
+  enum SequenceType { Star, Optional, OptionalRange };
+  auto processSequence = [this,&tokenPos,&tokenLen,&index,&str,&matchCharClass,
                           &isStartIdChar,&isIdChar,&match,&level,&pos](SequenceType type) -> bool
   {
     size_t startIndex = index;
@@ -515,11 +525,24 @@ bool Ex::Private::matchAt(size_t tokenPos,const std::string &str,Match &match,co
       if (type==Optional) index++; else index = str.length();
       tokenPos++;
     }
+    else if (type==OptionalRange && tok.kind()==PToken::Kind::BeginCapture)
+    {
+      size_t tokenStart = ++tokenPos;
+      while (tokenPos<tokenLen && data[tokenPos].kind()!=PToken::Kind::EndCapture) { tokenPos++; }
+      Match rangeMatch;
+      rangeMatch.init(&str);
+      bool found = matchAt(tokenStart,tokenPos,str,rangeMatch,index,level+1);
+      if (found)
+      {
+        index+=rangeMatch.length(); // (abc)? matches -> eat all
+      }
+      tokenPos++; // skip over EndCapture
+    }
     tokenPos++; // skip over end marker
     while ((int)index>=(int)startIndex)
     {
       // pattern 'x*xy' should match 'xy' and 'xxxxy'
-      bool found = matchAt(tokenPos,str,match,index,level+1);
+      bool found = matchAt(tokenPos,tokenLen,str,match,index,level+1);
       if (found)
       {
         match.setMatch(pos,index-pos+match.length());
@@ -530,10 +553,10 @@ bool Ex::Private::matchAt(size_t tokenPos,const std::string &str,Match &match,co
     return false;
   };
 
-  while (tokenPos<data.size())
+  while (tokenPos<tokenLen)
   {
     PToken tok = data[tokenPos];
-    //DBG("loop tokenPos=%zu token=%s\n",tokenPos,tok.kindStr());
+    DBG("loop tokenPos=%zu token=%s\n",tokenPos,tok.kindStr());
     if (tok.kind()==PToken::Kind::Character) // match literal character
     {
       char c_tok = tok.asciiValue();
@@ -603,7 +626,14 @@ bool Ex::Private::matchAt(size_t tokenPos,const std::string &str,Match &match,co
         case PToken::Kind::Star:
           return processSequence(Star);
         case PToken::Kind::Optional:
-          return processSequence(Optional);
+          if (tokenPos<tokenLen-1 && data[tokenPos+1].kind()==PToken::Kind::BeginCapture)
+          {
+            return processSequence(OptionalRange); // (...)?
+          }
+          else
+          {
+            return processSequence(Optional); // x?
+          }
         default:
           return false;
       }
@@ -682,7 +712,7 @@ bool Ex::match(const std::string &str,Match &match,size_t pos) const
   PToken tok = p->data[0];
   if (tok.kind()==PToken::Kind::BeginOfLine) // only test match at the given position
   {
-    found = p->matchAt(0,str,match,pos,0);
+    found = p->matchAt(0,p->data.size(),str,match,pos,0);
   }
   else
   {
@@ -699,7 +729,7 @@ bool Ex::match(const std::string &str,Match &match,size_t pos) const
     }
     while (pos<str.length()) // search for a match starting at pos
     {
-      found = p->matchAt(0,str,match,pos,0);
+      found = p->matchAt(0,p->data.size(),str,match,pos,0);
       if (found) break;
       pos++;
     }
index 025cc90..49a6f33 100644 (file)
@@ -57,21 +57,29 @@ static QCString align(DocHtmlCell *cell)
 
 RTFDocVisitor::RTFDocVisitor(TextStream &t,CodeOutputInterface &ci,
                              const QCString &langExt)
-  : DocVisitor(DocVisitor_RTF), m_t(t), m_ci(ci), m_insidePre(FALSE),
-    m_hide(FALSE), m_indentLevel(0), m_lastIsPara(FALSE), m_langExt(langExt)
+  : DocVisitor(DocVisitor_RTF), m_t(t), m_ci(ci), m_langExt(langExt)
 {
 }
 
 QCString RTFDocVisitor::getStyle(const QCString &name)
 {
-  QCString n = name + QCString().setNum(m_indentLevel);
+  QCString n = name + QCString().setNum(indentLevel());
   StyleData &sd = rtf_Style[n.str()];
   return sd.reference();
 }
 
+int RTFDocVisitor::indentLevel() const
+{
+  return std::min(m_indentLevel,maxIndentLevels-1);
+}
+
 void RTFDocVisitor::incIndentLevel()
 {
-  if (m_indentLevel<rtf_maxIndentLevels-1) m_indentLevel++;
+  m_indentLevel++;
+  if (m_indentLevel>=maxIndentLevels)
+  {
+    err("Maximum indent level (%d) exceeded while generating RTF output!\n",maxIndentLevels-1);
+  }
 }
 
 void RTFDocVisitor::decIndentLevel()
@@ -79,7 +87,7 @@ void RTFDocVisitor::decIndentLevel()
   if (m_indentLevel>0) m_indentLevel--;
 }
 
-  //--------------------------------------
+  //------------------------------------
   // visitor functions for leaf nodes
   //--------------------------------------
 
@@ -257,6 +265,9 @@ void RTFDocVisitor::visit(DocStyleChange *s)
     case DocStyleChange::Small:
       if (s->enable()) m_t << "{\\sub ";  else m_t << "} ";
       break;
+    case DocStyleChange::Cite:
+      if (s->enable()) m_t << "{\\i ";     else m_t << "} ";
+      break;
     case DocStyleChange::Preformatted:
       if (s->enable())
       {
@@ -275,6 +286,22 @@ void RTFDocVisitor::visit(DocStyleChange *s)
       break;
     case DocStyleChange::Div:  /* HTML only */ break;
     case DocStyleChange::Span: /* HTML only */ break;
+    case DocStyleChange::Details: /* emulation of the <details> tag */
+      if (s->enable())
+      {
+        m_t << "{\n";
+        m_t << "\\par\n";
+      }
+      else
+      {
+        m_t << "\\par";
+        m_t << "}\n";
+      }
+      m_lastIsPara=TRUE;
+      break;
+    case DocStyleChange::Summary: /* emulation of the <summary> tag inside a <details> tag */
+      if (s->enable()) m_t << "{\\b ";      else m_t << "} ";
+      break;
   }
 }
 
@@ -304,6 +331,16 @@ void RTFDocVisitor::visit(DocVerbatim *s)
       //m_t << "\\par\n";
       m_t << "}\n";
       break;
+    case DocVerbatim::JavaDocLiteral:
+      filter(s->text(),TRUE);
+      break;
+    case DocVerbatim::JavaDocCode:
+      m_t << "{\n";
+      m_t << "{\\f2 ";
+      filter(s->text(),TRUE);
+      m_t << "}";
+      m_t << "}\n";
+      break;
     case DocVerbatim::Verbatim:
       m_t << "{\n";
       m_t << "\\par\n";
@@ -402,7 +439,7 @@ void RTFDocVisitor::visit(DocAnchor *anc)
   QCString anchor;
   if (!anc->file().isEmpty())
   {
-    anchor+=anc->file();
+    anchor+=stripPath(anc->file());
   }
   if (!anc->file().isEmpty() && !anc->anchor().isEmpty())
   {
@@ -658,8 +695,10 @@ void RTFDocVisitor::visitPre(DocAutoList *l)
   if (m_hide) return;
   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocAutoList)}\n");
   m_t << "{\n";
-  rtf_listItemInfo[m_indentLevel].isEnum = l->isEnumList();
-  rtf_listItemInfo[m_indentLevel].number = 1;
+  int level = indentLevel();
+  m_listItemInfo[level].isEnum = l->isEnumList();
+  m_listItemInfo[level].type   = '1';
+  m_listItemInfo[level].number = 1;
   m_lastIsPara=FALSE;
 }
 
@@ -670,7 +709,7 @@ void RTFDocVisitor::visitPost(DocAutoList *)
   if (!m_lastIsPara) m_t << "\\par";
   m_t << "}\n";
   m_lastIsPara=TRUE;
-  if (!m_indentLevel) m_t << "\\par\n";
+  if (indentLevel()==0) m_t << "\\par\n";
 }
 
 void RTFDocVisitor::visitPre(DocAutoListItem *)
@@ -679,11 +718,12 @@ void RTFDocVisitor::visitPre(DocAutoListItem *)
   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocAutoListItem)}\n");
   if (!m_lastIsPara) m_t << "\\par\n";
   m_t << rtf_Style_Reset;
-  if (rtf_listItemInfo[m_indentLevel].isEnum)
+  int level = indentLevel();
+  if (m_listItemInfo[level].isEnum)
   {
     m_t << getStyle("ListEnum") << "\n";
-    m_t << rtf_listItemInfo[m_indentLevel].number << ".\\tab ";
-    rtf_listItemInfo[m_indentLevel].number++;
+    m_t << m_listItemInfo[level].number << ".\\tab ";
+    m_listItemInfo[level].number++;
   }
   else
   {
@@ -827,7 +867,7 @@ void RTFDocVisitor::visitPre(DocSimpleList *)
   if (m_hide) return;
   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleSect)}\n");
   m_t << "{\n";
-  rtf_listItemInfo[m_indentLevel].isEnum = FALSE;
+  m_listItemInfo[indentLevel()].isEnum = FALSE;
   m_lastIsPara=FALSE;
 }
 
@@ -860,8 +900,8 @@ void RTFDocVisitor::visitPre(DocSection *s)
   if (m_hide) return;
   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSection)}\n");
   if (!m_lastIsPara) m_t << "\\par\n";
-  m_t << "{\\bkmkstart " << rtfFormatBmkStr(s->file()+"_"+s->anchor()) << "}\n";
-  m_t << "{\\bkmkend " << rtfFormatBmkStr(s->file()+"_"+s->anchor()) << "}\n";
+  m_t << "{\\bkmkstart " << rtfFormatBmkStr(stripPath(s->file())+"_"+s->anchor()) << "}\n";
+  m_t << "{\\bkmkend " << rtfFormatBmkStr(stripPath(s->file())+"_"+s->anchor()) << "}\n";
   m_t << "{{" // start section
       << rtf_Style_Reset;
   QCString heading;
@@ -891,20 +931,21 @@ void RTFDocVisitor::visitPre(DocHtmlList *l)
   if (m_hide) return;
   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlList)}\n");
   m_t << "{\n";
-  rtf_listItemInfo[m_indentLevel].isEnum = l->type()==DocHtmlList::Ordered;
-  rtf_listItemInfo[m_indentLevel].number = 1;
-  rtf_listItemInfo[m_indentLevel].type   = '1';
+  int level = indentLevel();
+  m_listItemInfo[level].isEnum = l->type()==DocHtmlList::Ordered;
+  m_listItemInfo[level].number = 1;
+  m_listItemInfo[level].type   = '1';
   for (const auto &opt : l->attribs())
   {
     if (opt.name=="type")
     {
-      rtf_listItemInfo[m_indentLevel].type = opt.value[0];
+      m_listItemInfo[level].type = opt.value[0];
     }
     if (opt.name=="start")
     {
       bool ok;
       int val = opt.value.toInt(&ok);
-      if (ok) rtf_listItemInfo[m_indentLevel].number = val;
+      if (ok) m_listItemInfo[level].number = val;
     }
   }
   m_lastIsPara=FALSE;
@@ -918,38 +959,48 @@ void RTFDocVisitor::visitPost(DocHtmlList *)
   m_lastIsPara=TRUE;
 }
 
-void RTFDocVisitor::visitPre(DocHtmlListItem *)
+void RTFDocVisitor::visitPre(DocHtmlListItem *l)
 {
   if (m_hide) return;
   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlListItem)}\n");
   m_t << "\\par\n";
   m_t << rtf_Style_Reset;
-  if (rtf_listItemInfo[m_indentLevel].isEnum)
+  int level = indentLevel();
+  if (m_listItemInfo[level].isEnum)
   {
+    for (const auto &opt : l->attribs())
+    {
+      if (opt.name=="value")
+      {
+        bool ok;
+        int val = opt.value.toInt(&ok);
+        if (ok) m_listItemInfo[level].number = val;
+      }
+    }
     m_t << getStyle("ListEnum") << "\n";
-    switch (rtf_listItemInfo[m_indentLevel].type)
+    switch (m_listItemInfo[level].type)
     {
       case '1':
-        m_t << rtf_listItemInfo[m_indentLevel].number;
+        m_t << m_listItemInfo[level].number;
         break;
       case 'a':
-        m_t << integerToAlpha(rtf_listItemInfo[m_indentLevel].number,false);
+        m_t << integerToAlpha(m_listItemInfo[level].number,false);
         break;
       case 'A':
-        m_t << integerToAlpha(rtf_listItemInfo[m_indentLevel].number);
+        m_t << integerToAlpha(m_listItemInfo[level].number);
         break;
       case 'i':
-        m_t << integerToRoman(rtf_listItemInfo[m_indentLevel].number,false);
+        m_t << integerToRoman(m_listItemInfo[level].number,false);
         break;
       case 'I':
-        m_t << integerToRoman(rtf_listItemInfo[m_indentLevel].number);
+        m_t << integerToRoman(m_listItemInfo[level].number);
         break;
       default:
-        m_t << rtf_listItemInfo[m_indentLevel].number;
+        m_t << m_listItemInfo[level].number;
         break;
     }
     m_t << ".\\tab ";
-    rtf_listItemInfo[m_indentLevel].number++;
+    m_listItemInfo[level].number++;
   }
   else
   {
@@ -1020,12 +1071,23 @@ void RTFDocVisitor::visitPost(DocHtmlDescData *)
   m_lastIsPara=TRUE;
 }
 
-void RTFDocVisitor::visitPre(DocHtmlTable *)
+void RTFDocVisitor::visitPre(DocHtmlTable *t)
 {
   if (m_hide) return;
   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlTable)}\n");
   if (!m_lastIsPara) m_t << "\\par\n";
   m_lastIsPara=TRUE;
+  if (t->hasCaption())
+  {
+    DocHtmlCaption *c = t->caption();
+    m_t << "\\pard \\qc \\b";
+    if (!c->file().isEmpty())
+    {
+      m_t << "{\\bkmkstart " << rtfFormatBmkStr(stripPath(c->file())+"_"+c->anchor()) << "}\n";
+      m_t << "{\\bkmkend " << rtfFormatBmkStr(stripPath(c->file())+"_"+c->anchor()) << "}\n";
+    }
+    m_t << "{Table \\field\\flddirty{\\*\\fldinst { SEQ Table \\\\*Arabic }}{\\fldrslt {\\noproof 1}} ";
+  }
 }
 
 void RTFDocVisitor::visitPost(DocHtmlTable *)
@@ -1040,8 +1102,7 @@ void RTFDocVisitor::visitPost(DocHtmlTable *)
 void RTFDocVisitor::visitPre(DocHtmlCaption *)
 {
   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlCaption)}\n");
-  m_t << "\\pard \\qc \\b";
-  m_t << "{Table \\field\\flddirty{\\*\\fldinst { SEQ Table \\\\*Arabic }}{\\fldrslt {\\noproof 1}} ";
+  // start of caption is handled in the RTFDocVisitor::visitPre(DocHtmlTable *t)
 }
 
 void RTFDocVisitor::visitPost(DocHtmlCaption *)
@@ -1288,6 +1349,7 @@ void RTFDocVisitor::includePicturePostRTF(bool isTypeRTF, bool hasCaption, bool
 void RTFDocVisitor::visitPre(DocDotFile *df)
 {
   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocDotFile)}\n");
+  if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(RTF_OUTPUT)+"/"+stripPath(df->file()));
   writeDotFile(df);
 }
 
@@ -1299,6 +1361,7 @@ void RTFDocVisitor::visitPost(DocDotFile *df)
 void RTFDocVisitor::visitPre(DocMscFile *df)
 {
   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocMscFile)}\n");
+  if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(RTF_OUTPUT)+"/"+stripPath(df->file()));
   writeMscFile(df);
 }
 
@@ -1311,6 +1374,7 @@ void RTFDocVisitor::visitPost(DocMscFile *df)
 void RTFDocVisitor::visitPre(DocDiaFile *df)
 {
   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocDiaFile)}\n");
+  if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(RTF_OUTPUT)+"/"+stripPath(df->file()));
   writeDiaFile(df);
 }
 
@@ -1624,7 +1688,7 @@ void RTFDocVisitor::visitPre(DocXRefItem *x)
     QCString refName;
     if (!x->file().isEmpty())
     {
-      refName+=x->file();
+      refName+=stripPath(x->file());
     }
     if (!x->file().isEmpty() && !x->anchor().isEmpty())
     {
@@ -1798,7 +1862,7 @@ void RTFDocVisitor::startLink(const QCString &ref,const QCString &file,const QCS
     QCString refName;
     if (!file.isEmpty())
     {
-      refName+=file;
+      refName+=stripPath(file);
     }
     if (!file.isEmpty() && !anchor.isEmpty())
     {
index f7cc2b5..9d8a3af 100644 (file)
@@ -147,6 +147,8 @@ class RTFDocVisitor : public DocVisitor
                    const QCString &anchor);
     void endLink(const QCString &ref);
     QCString getStyle(const QCString &name);
+
+    int indentLevel() const;
     void incIndentLevel();
     void decIndentLevel();
 
@@ -165,11 +167,20 @@ class RTFDocVisitor : public DocVisitor
 
     TextStream &m_t;
     CodeOutputInterface &m_ci;
-    bool m_insidePre;
-    bool m_hide;
-    int m_indentLevel;
-    bool m_lastIsPara;
+    bool m_insidePre = false;
+    bool m_hide = false;
+    bool m_lastIsPara = false;
     QCString m_langExt;
+
+    static const int maxIndentLevels = 13;
+    int m_indentLevel = 0;
+    struct RTFListItemInfo
+    {
+      bool isEnum = false;
+      int number = 1;
+      char type = '1';
+    };
+    RTFListItemInfo m_listItemInfo[maxIndentLevels];
 };
 
 #endif
index f653245..e740d1f 100644 (file)
@@ -279,23 +279,15 @@ void RTFGenerator::beginRTFDocument()
   m_t << "{\\widctlpar\\adjustright \\fs20\\cgrid \\snext0 Normal;}\n";
 
   // set the paper dimensions according to PAPER_TYPE
-  QCString paperName = Config_getEnum(PAPER_TYPE);
+  static auto paperType = Config_getEnum(PAPER_TYPE);
   m_t << "{";
-  if (paperName=="a4")
+  switch (paperType)
   {
-    m_t << "\\paperw11900\\paperh16840"; // width & height values are inches * 1440
-  }
-  else if (paperName=="letter")
-  {
-    m_t << "\\paperw12240\\paperh15840";
-  }
-  else if (paperName=="legal")
-  {
-    m_t << "\\paperw12240\\paperh20160";
-  }
-  else if (paperName=="executive")
-  {
-    m_t << "\\paperw10440\\paperh15120";
+    // width & height values are inches * 1440
+    case PAPER_TYPE_t::a4:        m_t << "\\paperw11900\\paperh16840"; break;
+    case PAPER_TYPE_t::letter:    m_t << "\\paperw12240\\paperh15840"; break;
+    case PAPER_TYPE_t::legal:     m_t << "\\paperw12240\\paperh20160"; break;
+    case PAPER_TYPE_t::executive: m_t << "\\paperw10440\\paperh15120"; break;
   }
   m_t << "\\margl1800\\margr1800\\margt1440\\margb1440\\gutter0\\ltrsect}\n";
 
@@ -413,7 +405,7 @@ void RTFGenerator::startIndexSection(IndexSections is)
 {
   //QCString paperName;
 
-  m_listLevel = 0;
+  //m_indentLevel = 0;
 
   switch (is)
   {
@@ -1014,7 +1006,7 @@ void RTFGenerator::startIndexList()
   DBG_RTF(m_t << "{\\comment (startIndexList)}\n")
   m_t << "{\n";
   m_t << "\\par\n";
-  incrementIndentLevel();
+  incIndentLevel();
   m_t << rtf_Style_Reset << rtf_LCList_DepthStyle() << "\n";
   m_omitParagraph = TRUE;
 }
@@ -1028,26 +1020,29 @@ void RTFGenerator::endIndexList()
     m_omitParagraph = TRUE;
   }
   m_t << "}";
-  decrementIndentLevel();
+  decIndentLevel();
 }
 
 /*! start bullet list */
 void RTFGenerator::startItemList()
 {
   newParagraph();
-  DBG_RTF(m_t << "{\\comment (startItemList level=" << m_listLevel << ") }\n")
+  incIndentLevel();
+  int level = indentLevel();
+  DBG_RTF(m_t << "{\\comment (startItemList level=" << level << ") }\n")
   m_t << "{";
-  incrementIndentLevel();
-  rtf_listItemInfo[m_listLevel].isEnum = FALSE;
+  m_listItemInfo[level].number = 1;
+  m_listItemInfo[level].isEnum = false;
+  m_listItemInfo[level].type   = '1';
 }
 
 /*! end bullet list */
 void RTFGenerator::endItemList()
 {
   newParagraph();
-  DBG_RTF(m_t << "{\\comment (endItemList level=" << m_listLevel << ")}\n")
+  DBG_RTF(m_t << "{\\comment (endItemList level=" << indentLevel() << ")}\n")
   m_t << "}";
-  decrementIndentLevel();
+  decIndentLevel();
   m_omitParagraph = TRUE;
 }
 
@@ -1057,11 +1052,12 @@ void RTFGenerator::startItemListItem()
   DBG_RTF(m_t << "{\\comment (startItemListItem)}\n")
   newParagraph();
   m_t << rtf_Style_Reset;
-  if (rtf_listItemInfo[m_listLevel].isEnum)
+  int level = indentLevel();
+  if (m_listItemInfo[level].isEnum)
   {
     m_t << rtf_EList_DepthStyle() << "\n";
-    m_t << rtf_listItemInfo[m_listLevel].number << ".\\tab ";
-    rtf_listItemInfo[m_listLevel].number++;
+    m_t << m_listItemInfo[level].number << ".\\tab ";
+    m_listItemInfo[level].number++;
   }
   else
   {
@@ -1139,7 +1135,7 @@ void RTFGenerator::writeStartAnnoItem(const QCString &,const QCString &f,
   if (!f.isEmpty() && Config_getBool(RTF_HYPERLINKS))
   {
     m_t << "{\\field {\\*\\fldinst { HYPERLINK  \\\\l \"";
-    m_t << rtfFormatBmkStr(f);
+    m_t << rtfFormatBmkStr(stripPath(f));
     m_t << "\" }{}";
     m_t << "}{\\fldrslt {\\cs37\\ul\\cf2 ";
 
@@ -1244,7 +1240,7 @@ void RTFGenerator::startTextLink(const QCString &f,const QCString &anchor)
     QCString ref;
     if (!f.isEmpty())
     {
-      ref+=f;
+      ref+=stripPath(f);
     }
     if (!anchor.isEmpty())
     {
@@ -1275,7 +1271,7 @@ void RTFGenerator::writeObjectLink(const QCString &ref, const QCString &f,
     QCString refName;
     if (!f.isEmpty())
     {
-      refName+=f;
+      refName+=stripPath(f);
     }
     if (!anchor.isEmpty())
     {
@@ -1333,7 +1329,7 @@ void RTFGenerator::writeCodeLink(CodeSymbolType,
     QCString refName;
     if (!f.isEmpty())
     {
-      refName+=f;
+      refName+=stripPath(f);
     }
     if (!anchor.isEmpty())
     {
@@ -1466,7 +1462,7 @@ void RTFGenerator::endDoxyAnchor(const QCString &fName,const QCString &anchor)
   QCString ref;
   if (!fName.isEmpty())
   {
-    ref+=fName;
+    ref+=stripPath(fName);
   }
   if (!anchor.isEmpty())
   {
@@ -1500,7 +1496,7 @@ void RTFGenerator::addIndexItem(const QCString &s1,const QCString &s2)
 
 void RTFGenerator::startIndent()
 {
-  incrementIndentLevel();
+  incIndentLevel();
   DBG_RTF(m_t << "{\\comment (startIndent) }\n")
   m_t << "{\n";
   m_t << rtf_Style_Reset << rtf_CList_DepthStyle() << "\n";
@@ -1509,7 +1505,7 @@ void RTFGenerator::startIndent()
 void RTFGenerator::endIndent()
 {
   m_t << "}\n";
-  decrementIndentLevel();
+  decIndentLevel();
 }
 
 
@@ -1545,7 +1541,7 @@ void RTFGenerator::startMemberDescription(const QCString &,const QCString &,bool
 {
   DBG_RTF(m_t << "{\\comment (startMemberDescription)}\n")
   m_t << "{\n";
-  incrementIndentLevel();
+  incIndentLevel();
   m_t << rtf_Style_Reset << rtf_CList_DepthStyle();
   startEmphasis();
 }
@@ -1555,7 +1551,7 @@ void RTFGenerator::endMemberDescription()
   DBG_RTF(m_t << "{\\comment (endMemberDescription)}\n")
   endEmphasis();
   //newParagraph();
-  decrementIndentLevel();
+  decIndentLevel();
   m_t << "\\par";
   m_t << "}\n";
   m_omitParagraph = TRUE;
@@ -1727,7 +1723,7 @@ void RTFGenerator::writeAnchor(const QCString &fileName,const QCString &name)
   QCString anchor;
   if (!fileName.isEmpty())
   {
-    anchor+=fileName;
+    anchor+=stripPath(fileName);
   }
   if (!fileName.isEmpty() && !name.isEmpty())
   {
@@ -1747,7 +1743,7 @@ void RTFGenerator::writeAnchor(const QCString &fileName,const QCString &name)
 void RTFGenerator::writeRTFReference(const QCString &label)
 {
   m_t << "{\\field\\fldedit {\\*\\fldinst PAGEREF ";
-  m_t << rtfFormatBmkStr(label);
+  m_t << rtfFormatBmkStr(stripPath(label));
   m_t << " \\\\*MERGEFORMAT}{\\fldrslt pagenum}}";
 }
 
@@ -1862,63 +1858,67 @@ void RTFGenerator::endDescTableData()
 
 // a style for list formatted as a "bulleted list"
 
-void RTFGenerator::incrementIndentLevel()
+int RTFGenerator::indentLevel() const
+{
+  return std::min(m_indentLevel,maxIndentLevels-1);
+}
+
+void RTFGenerator::incIndentLevel()
 {
-  m_listLevel++;
-  if (m_listLevel>rtf_maxIndentLevels-1)
+  m_indentLevel++;
+  if (m_indentLevel>=maxIndentLevels)
   {
-    err("Maximum indent level (%d) exceeded while generating RTF output!\n",rtf_maxIndentLevels);
-    m_listLevel=rtf_maxIndentLevels-1;
+    err("Maximum indent level (%d) exceeded while generating RTF output!\n",maxIndentLevels);
   }
 }
 
-void RTFGenerator::decrementIndentLevel()
+void RTFGenerator::decIndentLevel()
 {
-  m_listLevel--;
-  if (m_listLevel<0)
+  m_indentLevel--;
+  if (m_indentLevel<0)
   {
     err("Negative indent level while generating RTF output!\n");
-    m_listLevel=0;
+    m_indentLevel=0;
   }
 }
 
 // a style for list formatted with "list continue" style
 QCString RTFGenerator::rtf_CList_DepthStyle()
 {
-  QCString n=makeIndexName("ListContinue",m_listLevel);
+  QCString n=makeIndexName("ListContinue",indentLevel());
   return rtf_Style[n.str()].reference();
 }
 
 // a style for list formatted as a "latext style" table of contents
 QCString RTFGenerator::rtf_LCList_DepthStyle()
 {
-  QCString n=makeIndexName("LatexTOC",m_listLevel);
+  QCString n=makeIndexName("LatexTOC",indentLevel());
   return rtf_Style[n.str()].reference();
 }
 
 // a style for list formatted as a "bullet" style
 QCString RTFGenerator::rtf_BList_DepthStyle()
 {
-  QCString n=makeIndexName("ListBullet",m_listLevel);
+  QCString n=makeIndexName("ListBullet",indentLevel());
   return rtf_Style[n.str()].reference();
 }
 
 // a style for list formatted as a "enumeration" style
 QCString RTFGenerator::rtf_EList_DepthStyle()
 {
-  QCString n=makeIndexName("ListEnum",m_listLevel);
+  QCString n=makeIndexName("ListEnum",indentLevel());
   return rtf_Style[n.str()].reference();
 }
 
 QCString RTFGenerator::rtf_DList_DepthStyle()
 {
-  QCString n=makeIndexName("DescContinue",m_listLevel);
+  QCString n=makeIndexName("DescContinue",indentLevel());
   return rtf_Style[n.str()].reference();
 }
 
 QCString RTFGenerator::rtf_Code_DepthStyle()
 {
-  QCString n=makeIndexName("CodeExample",m_listLevel);
+  QCString n=makeIndexName("CodeExample",indentLevel());
   return rtf_Style[n.str()].reference();
 }
 
@@ -2087,7 +2087,7 @@ static bool preProcessFile(Dir &d,const QCString &infName, TextStream &t, bool b
   std::ifstream f(infName.str(),std::ifstream::in);
   if (!f.is_open())
   {
-    err("problems opening rtf file %s for reading\n",infName.data());
+    err("problems opening rtf file '%s' for reading\n",infName.data());
     return false;
   }
 
@@ -2112,7 +2112,7 @@ static bool preProcessFile(Dir &d,const QCString &infName, TextStream &t, bool b
   {
     line+='\n';
     size_t pos;
-    if ((pos=prevLine.find("INCLUDETEXT"))!=std::string::npos)
+    if ((pos=prevLine.find("INCLUDETEXT \""))!=std::string::npos)
     {
       size_t startNamePos  = prevLine.find('"',pos)+1;
       size_t endNamePos    = prevLine.find('"',startNamePos);
@@ -2355,7 +2355,7 @@ void RTFGenerator::startMemberGroupHeader(bool hasHeader)
 {
   DBG_RTF(m_t << "{\\comment startMemberGroupHeader}\n")
   m_t << "{\n";
-  if (hasHeader) incrementIndentLevel();
+  if (hasHeader) incIndentLevel();
   m_t << rtf_Style_Reset << rtf_Style["GroupHeader"].reference();
 }
 
@@ -2388,7 +2388,7 @@ void RTFGenerator::startMemberGroup()
 void RTFGenerator::endMemberGroup(bool hasHeader)
 {
   DBG_RTF(m_t << "{\\comment endMemberGroup}\n")
-  if (hasHeader) decrementIndentLevel();
+  if (hasHeader) decIndentLevel();
   m_t << "}";
 }
 
@@ -2403,7 +2403,7 @@ void RTFGenerator::startExamples()
   endBold();
   m_t << "}";
   newParagraph();
-  incrementIndentLevel();
+  incIndentLevel();
   m_t << rtf_Style_Reset << rtf_DList_DepthStyle();
 }
 
@@ -2412,7 +2412,7 @@ void RTFGenerator::endExamples()
   DBG_RTF(m_t << "{\\comment (endExamples)}\n")
   m_omitParagraph = FALSE;
   newParagraph();
-  decrementIndentLevel();
+  decIndentLevel();
   m_omitParagraph = TRUE;
   m_t << "}";
 }
@@ -2428,7 +2428,7 @@ void RTFGenerator::startParamList(ParamListTypes,const QCString &title)
   endBold();
   m_t << "}";
   newParagraph();
-  incrementIndentLevel();
+  incIndentLevel();
   m_t << rtf_Style_Reset << rtf_DList_DepthStyle();
 }
 
@@ -2436,7 +2436,7 @@ void RTFGenerator::endParamList()
 {
   DBG_RTF(m_t << "{\\comment (endParamList)}\n")
   newParagraph();
-  decrementIndentLevel();
+  decIndentLevel();
   m_omitParagraph = TRUE;
   m_t << "}";
 }
@@ -2513,7 +2513,7 @@ void RTFGenerator::startConstraintList(const QCString &header)
   endBold();
   m_t << "}";
   newParagraph();
-  incrementIndentLevel();
+  incIndentLevel();
   m_t << rtf_Style_Reset << rtf_DList_DepthStyle();
 }
 
@@ -2558,7 +2558,7 @@ void RTFGenerator::endConstraintList()
 {
   DBG_RTF(m_t << "{\\comment (endConstraintList)}\n")
   newParagraph();
-  decrementIndentLevel();
+  decIndentLevel();
   m_omitParagraph = TRUE;
   m_t << "}";
 }
@@ -2673,7 +2673,7 @@ void RTFGenerator::endInlineMemberDoc()
   m_t << "\\cell }{\\row }\n";
 }
 
-void RTFGenerator::writeLineNumber(const QCString &ref,const QCString &fileName,const QCString &anchor,int l)
+void RTFGenerator::writeLineNumber(const QCString &ref,const QCString &fileName,const QCString &anchor,int l,bool writeLineAnchor)
 {
   bool rtfHyperlinks = Config_getBool(RTF_HYPERLINKS);
 
@@ -2687,9 +2687,9 @@ void RTFGenerator::writeLineNumber(const QCString &ref,const QCString &fileName,
     if (!m_sourceFileName.isEmpty())
     {
       lineAnchor.sprintf("_l%05d",l);
-      lineAnchor.prepend(stripExtensionGeneral(m_sourceFileName, ".rtf"));
+      lineAnchor.prepend(stripExtensionGeneral(stripPath(m_sourceFileName), ".rtf"));
     }
-    bool showTarget = rtfHyperlinks && !lineAnchor.isEmpty();
+    bool showTarget = rtfHyperlinks && !lineAnchor.isEmpty() && writeLineAnchor;
     if (showTarget)
     {
         m_t << "{\\bkmkstart ";
index c9bce4c..dae336b 100644 (file)
@@ -127,7 +127,7 @@ class RTFGenerator : public OutputGenerator
     void writeAnchor(const QCString &fileName,const QCString &name);
     void startCodeFragment(const QCString &style);
     void endCodeFragment(const QCString &style);
-    void writeLineNumber(const QCString &,const QCString &,const QCString &,int l);
+    void writeLineNumber(const QCString &,const QCString &,const QCString &,int l, bool);
     void startCodeLine(bool);
     void endCodeLine();
     void startEmphasis() { m_t << "{\\i ";  }
@@ -273,8 +273,6 @@ class RTFGenerator : public OutputGenerator
     QCString rtf_LCList_DepthStyle();
     QCString rtf_DList_DepthStyle();
     QCString rtf_Code_DepthStyle();
-    void incrementIndentLevel();
-    void decrementIndentLevel();
     void beginRTFDocument();
     void beginRTFChapter();
     void beginRTFSection();
@@ -284,14 +282,28 @@ class RTFGenerator : public OutputGenerator
     void rtfwriteRuler_thin();
     void writeRTFReference(const QCString &label);
 
+    int indentLevel() const;
+    void incIndentLevel();
+    void decIndentLevel();
+
     QCString m_sourceFileName;
     int  m_col = 0;
     bool m_bstartedBody = false;  // has startbody been called yet?
-    int  m_listLevel = 0; // // RTF does not really have a additive indent...manually set list level.
     bool m_omitParagraph = false; // should a the next paragraph command be ignored?
     int  m_numCols = 0; // number of columns in a table
     QCString m_relPath;
     bool m_doxyCodeLineOpen = false;
+
+    // RTF does not really have a additive indent...manually set list level.
+    static const int maxIndentLevels = 13;
+    int m_indentLevel = 0;
+    struct RTFListItemInfo
+    {
+      bool isEnum = false;
+      int number = 1;
+      char type = '1';
+    };
+    RTFListItemInfo m_listItemInfo[maxIndentLevels];
 };
 
 #endif
index 07bc3dd..65f47b1 100644 (file)
@@ -20,8 +20,6 @@
 #include "message.h"
 #include "regex.h"
 
-RTFListItemInfo rtf_listItemInfo[rtf_maxIndentLevels];
-
 QCString rtf_title;
 QCString rtf_subject;
 QCString rtf_comments;
index a946b37..fbd6882 100644 (file)
@@ -35,17 +35,6 @@ extern QCString rtf_documentType;
 extern QCString rtf_documentId;
 extern QCString rtf_keywords;
 
-struct RTFListItemInfo
-{
-  bool isEnum;
-  int number;
-  char type;
-};
-
-const int rtf_maxIndentLevels = 13;
-
-extern RTFListItemInfo rtf_listItemInfo[rtf_maxIndentLevels];
-
 struct Rtf_Style_Default
 {
   const char *name;
index a7ec675..d7f8b37 100644 (file)
 %option extra-type="struct scannerYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve typesafety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -105,7 +109,7 @@ struct scannerYY_state
   int              yyBegLineNr  = 1 ;
   int              yyColNr      = 1 ;
   int              yyBegColNr   = 1 ;
-  QCString         yyFileName;
+  QCString         fileName;
   MethodTypes      mtype = Method;
   bool             stat = false;
   Specifier        virt = Normal;
@@ -134,6 +138,7 @@ struct scannerYY_state
 
   bool             insideCppQuote = false;
   bool             insideProtocolList = false;
+  bool             doxygenComment = false;
 
   int              argRoundCount = 0;
   int              argSquareCount = 0;
@@ -185,7 +190,7 @@ struct scannerYY_state
   bool             odlProp = false;
 
   bool             lexInit = false;
-  bool             externC = false;
+  bool             externLinkage = false;
 
   QCString         delimiter;
 
@@ -209,6 +214,7 @@ static inline int computeIndent(const char *s,int startIndent);
 static QCString stripQuotes(const char *s);
 static bool nameIsOperator(QCString &name);
 void fixArgumentListForJavaScript(ArgumentList &al);
+static bool startOfRequiresExpression(const QCString &req);
 
 // forward declarations for statefull functions
 static void initParser(yyscan_t yyscanner);
@@ -230,6 +236,10 @@ static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
 #undef  YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
+
 %}
 
        /* start command character */
@@ -266,8 +276,12 @@ CCS   "/\*"
 CCE   "*\/"
   // Cpp comment 
 CPPC  "/\/"
+  // doxygen C start comment
+DCOMMC ("/\*!"|"/\**")
+  // doxygen Cpp start comment
+DCOMMCPP ("/\/!"|"/\/\/")
   // doxygen start comment
-DCOMM ("/\*!"|"/\**"|"/\/!"|"/\/\/")
+DCOMM {DCOMMC}|{DCOMMCPP}
 
   // Optional any character
 ANYopt .*
@@ -301,7 +315,6 @@ NONLopt [^\n]*
 %x      FindMembersPHP
 %x      FindMemberName
 %x      FindFields
-%x      FindFieldArg
 %x      Function
 %x      FuncRound
 %x      ExcpRound
@@ -326,7 +339,6 @@ NONLopt [^\n]*
 %x      SkipC11Inits
 %x      SkipC11Attribute
 %x      SkipCPP
-%x      SkipCPPBlock
 %x      SkipComment
 %x      SkipCxxComment
 %x      SkipCurlyBlock
@@ -334,7 +346,6 @@ NONLopt [^\n]*
 %x      Sharp
 %x      SkipRound
 %x      SkipSquare
-%x      SkipRemainder
 %x      StaticAssert
 %x      DeclType
 %x      TypedefName
@@ -360,7 +371,6 @@ NONLopt [^\n]*
 %x      ObjCPropAttr
 %x      ObjCSkipStatement
 %x      QtPropType
-%x      QtPropName
 %x      QtPropAttr
 %x      QtPropRead
 %x      QtPropWrite
@@ -395,7 +405,6 @@ NONLopt [^\n]*
 %x      Specialization
 %x      SpecializationSingleQuote
 %x      SpecializationDoubleQuote
-%x      FuncPtrInit
 %x      FuncFunc
 %x      FuncFuncEnd
 %x      FuncFuncType
@@ -768,7 +777,7 @@ NONLopt [^\n]*
                                           else
                                           {
                                             lineCount(yyscanner);
-                                            yyextra->current->fileName  = yyextra->yyFileName;
+                                            yyextra->current->fileName  = yyextra->fileName;
                                             yyextra->current->startLine = yyextra->yyLineNr;
                                             yyextra->current->startColumn = yyextra->yyColNr;
                                             yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -910,7 +919,7 @@ NONLopt [^\n]*
                                             lineCount(yyscanner);
                                             yyextra->current->bodyLine = yyextra->yyLineNr;
                                             yyextra->current->bodyColumn = yyextra->yyColNr;
-                                            yyextra->current->fileName = yyextra->yyFileName ;
+                                            yyextra->current->fileName = yyextra->fileName ;
                                             yyextra->current->startLine = yyextra->yyLineNr ;
                                             yyextra->current->startColumn = yyextra->yyColNr;
                                             yyextra->current->args.resize(0);
@@ -927,7 +936,7 @@ NONLopt [^\n]*
                                             lineCount(yyscanner);
                                             yyextra->current->bodyLine = yyextra->yyLineNr;
                                             yyextra->current->bodyColumn = yyextra->yyColNr;
-                                            yyextra->current->fileName = yyextra->yyFileName ;
+                                            yyextra->current->fileName = yyextra->fileName ;
                                             yyextra->current->startLine = yyextra->yyLineNr ;
                                             yyextra->current->startColumn = yyextra->yyColNr;
                                             yyextra->current->args.resize(0);
@@ -1001,6 +1010,16 @@ NONLopt [^\n]*
 <ObjCPropAttr>")"                       {
                                           BEGIN(FindMembers);
                                         }
+<FindMembers>"@"{ID}("."{ID})+          {
+                                          if (yyextra->insideJava) // Java annotation
+                                          {
+                                            // skip annotation
+                                          }
+                                          else
+                                          {
+                                            REJECT;
+                                          }
+                                        }
 <FindMembers>"@"{ID}                    {
                                           if (yyextra->insideJava) // Java annotation
                                           {
@@ -1036,7 +1055,7 @@ NONLopt [^\n]*
                                           yyextra->current->name = substitute(yyextra->current->name,"\\","::");
                                           yyextra->current->section = Entry::NAMESPACE_SEC;
                                           yyextra->current->type = "namespace" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1054,7 +1073,7 @@ NONLopt [^\n]*
                                           yyextra->curlyCount=0;
                                           BEGIN( ReadNSBody );
                                         }
-<FindMembers>{B}*"initonly"{BN}+        {
+<FindMembers>{B}*"initonly"{BN}+        { if (yyextra->insideJava) REJECT;
                                           yyextra->current->type += " initonly ";
                                           if (yyextra->insideCli) yyextra->current->spec |= Entry::Initonly;
                                           lineCount(yyscanner);
@@ -1063,7 +1082,7 @@ NONLopt [^\n]*
                                           yyextra->current->stat = TRUE;
                                           lineCount(yyscanner);
                                         }
-<FindMembers>{B}*"extern"{BN}+          {
+<FindMembers>{B}*"extern"{BN}+          { if (yyextra->insideJava) REJECT;
                                           yyextra->current->stat = FALSE;
                                           yyextra->current->explicitExternal = TRUE;
                                           lineCount(yyscanner);
@@ -1079,21 +1098,17 @@ NONLopt [^\n]*
                                             REJECT;
                                           }
                                         }
-<FindMembers>{B}*"virtual"{BN}+         { yyextra->current->type += " virtual ";
+<FindMembers>{B}*"virtual"{BN}+         { if (yyextra->insideJava) REJECT;
+                                          yyextra->current->type += " virtual ";
                                           yyextra->current->virt = Virtual;
                                           lineCount(yyscanner);
                                         }
 <FindMembers>{B}*"constexpr"{BN}+       {
                                           if (yyextra->insideCpp)
                                           {
-                                            yyextra->current->type += " constexpr ";
                                             yyextra->current->spec |= Entry::ConstExpr;
-                                            lineCount(yyscanner);
-                                          }
-                                          else
-                                          {
-                                            REJECT;
                                           }
+                                          REJECT;
                                         }
 <FindMembers>{B}*"published"{BN}+       { // UNO IDL published keyword
                                           if (yyextra->insideIDL)
@@ -1125,16 +1140,20 @@ NONLopt [^\n]*
                                           }
                                           lineCount(yyscanner);
                                         }
-<FindMembers>{B}*"inline"{BN}+          { yyextra->current->spec|=Entry::Inline;
+<FindMembers>{B}*"inline"{BN}+          { if (yyextra->insideJava) REJECT;
+                                          yyextra->current->spec|=Entry::Inline;
                                           lineCount(yyscanner);
                                         }
-<FindMembers>{B}*"mutable"{BN}+         { yyextra->current->spec|=Entry::Mutable;
+<FindMembers>{B}*"mutable"{BN}+         { if (yyextra->insideJava) REJECT;
+                                          yyextra->current->spec|=Entry::Mutable;
                                           lineCount(yyscanner);
                                         }
-<FindMembers>{B}*"explicit"{BN}+        { yyextra->current->spec|=Entry::Explicit;
+<FindMembers>{B}*"explicit"{BN}+        { if (yyextra->insideJava) REJECT;
+                                          yyextra->current->spec|=Entry::Explicit;
                                           lineCount(yyscanner);
                                         }
-<FindMembers>{B}*"local"{BN}+           { yyextra->current->spec|=Entry::Local;
+<FindMembers>{B}*"local"{BN}+           { if (yyextra->insideJava) REJECT;
+                                          yyextra->current->spec|=Entry::Local;
                                           lineCount(yyscanner);
                                         }
 <FindMembers>{B}*"@required"{BN}+       { // Objective C 2.0 protocol required section
@@ -1151,11 +1170,11 @@ NONLopt [^\n]*
                                         }
   */
 <FindMembers>{B}*"typename"{BN}+        { lineCount(yyscanner); }
-<FindMembers>{B}*"namespace"{BNopt}/[^a-z_A-Z0-9] {
+<FindMembers>{B}*"namespace"{BNopt}/[^a-z_A-Z0-9] { if (yyextra->insideJava) REJECT;
                                           yyextra->isTypedef=FALSE;
                                           yyextra->current->section = Entry::NAMESPACE_SEC;
                                           yyextra->current->type = "namespace" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1177,7 +1196,7 @@ NONLopt [^\n]*
                                             yyextra->isTypedef=FALSE;
                                             yyextra->current->section = Entry::NAMESPACE_SEC;
                                             yyextra->current->type = "module" ;
-                                            yyextra->current->fileName  = yyextra->yyFileName;
+                                            yyextra->current->fileName  = yyextra->fileName;
                                             yyextra->current->startLine = yyextra->yyLineNr;
                                             yyextra->current->startColumn = yyextra->yyColNr;
                                             yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1202,7 +1221,7 @@ NONLopt [^\n]*
                                             yyextra->isTypedef=FALSE;
                                             yyextra->current->section = Entry::NAMESPACE_SEC;
                                             yyextra->current->type = "library" ;
-                                            yyextra->current->fileName  = yyextra->yyFileName;
+                                            yyextra->current->fileName  = yyextra->fileName;
                                             yyextra->current->startLine = yyextra->yyLineNr;
                                             yyextra->current->startColumn = yyextra->yyColNr;
                                             yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1222,7 +1241,7 @@ NONLopt [^\n]*
                                             yyextra->isTypedef=FALSE;
                                             yyextra->current->section = Entry::NAMESPACE_SEC;
                                             yyextra->current->type = "constants";
-                                            yyextra->current->fileName  = yyextra->yyFileName;
+                                            yyextra->current->fileName  = yyextra->fileName;
                                             yyextra->current->startLine = yyextra->yyLineNr;
                                             yyextra->current->startColumn = yyextra->yyColNr;
                                             yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1246,7 +1265,7 @@ NONLopt [^\n]*
                                               (yyextra->current->spec & (Entry::Optional|Entry::Published));
                                             addType(yyscanner);
                                             yyextra->current->type += " service " ;
-                                            yyextra->current->fileName  = yyextra->yyFileName;
+                                            yyextra->current->fileName  = yyextra->fileName;
                                             yyextra->current->startLine = yyextra->yyLineNr;
                                             yyextra->current->bodyLine  = yyextra->yyLineNr;
                                             yyextra->current->bodyColumn = yyextra->yyColNr;
@@ -1268,7 +1287,7 @@ NONLopt [^\n]*
                                               (yyextra->current->spec & Entry::Published); // preserve
                                             addType(yyscanner);
                                             yyextra->current->type += " singleton " ;
-                                            yyextra->current->fileName  = yyextra->yyFileName;
+                                            yyextra->current->fileName  = yyextra->fileName;
                                             yyextra->current->startLine = yyextra->yyLineNr;
                                             yyextra->current->bodyLine  = yyextra->yyLineNr;
                                             yyextra->current->bodyColumn = yyextra->yyColNr;
@@ -1291,7 +1310,7 @@ NONLopt [^\n]*
                                                 (yyextra->current->spec & (Entry::Optional|Entry::Published|Entry::Local));
                                             addType(yyscanner);
                                             yyextra->current->type += " interface" ;
-                                            yyextra->current->fileName  = yyextra->yyFileName;
+                                            yyextra->current->fileName  = yyextra->fileName;
                                             yyextra->current->startLine = yyextra->yyLineNr;
                                             yyextra->current->startColumn = yyextra->yyColNr;
                                             yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1313,7 +1332,7 @@ NONLopt [^\n]*
                                           yyextra->current->protection = yyextra->protection = Public ;
                                           addType(yyscanner);
                                           yyextra->current->type += " implementation" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
                                           yyextra->current->bodyColumn = yyextra->yyColNr;
@@ -1332,7 +1351,7 @@ NONLopt [^\n]*
                                           yyextra->current->protection = yyextra->protection = Public ;
                                           addType(yyscanner);
                                           yyextra->current->type += " interface" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1349,7 +1368,7 @@ NONLopt [^\n]*
                                           yyextra->current->protection = yyextra->protection = Public ;
                                           addType(yyscanner);
                                           yyextra->current->type += " protocol" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1357,6 +1376,7 @@ NONLopt [^\n]*
                                           BEGIN( CompoundName );
                                         }
 <FindMembers>{B}*"exception"{BN}+       { // Corba IDL/Slice exception
+                                          if (yyextra->insideJava) REJECT;
                                           yyextra->isTypedef=FALSE;
                                           yyextra->current->section = Entry::CLASS_SEC;
                                           // preserve UNO IDL, Slice local
@@ -1365,7 +1385,7 @@ NONLopt [^\n]*
                                             (yyextra->current->spec & Entry::Local);
                                           addType(yyscanner);
                                           yyextra->current->type += " exception" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1401,7 +1421,7 @@ NONLopt [^\n]*
                                             yyextra->current->type += " volatile";
                                           }
                                           yyextra->current->type += " class" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1422,7 +1442,7 @@ NONLopt [^\n]*
                                           yyextra->current->spec = Entry::Value;
                                           addType(yyscanner);
                                           yyextra->current->type += " value class" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1438,7 +1458,7 @@ NONLopt [^\n]*
                                           yyextra->current->spec = Entry::Ref;
                                           addType(yyscanner);
                                           yyextra->current->type += " ref class" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1454,7 +1474,7 @@ NONLopt [^\n]*
                                           yyextra->current->spec = Entry::Interface;
                                           addType(yyscanner);
                                           yyextra->current->type += " interface class" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1470,7 +1490,7 @@ NONLopt [^\n]*
                                             yyextra->current->section = Entry::CLASS_SEC;
                                             addType(yyscanner);
                                             yyextra->current->type += " coclass" ;
-                                            yyextra->current->fileName  = yyextra->yyFileName;
+                                            yyextra->current->fileName  = yyextra->fileName;
                                             yyextra->current->startLine = yyextra->yyLineNr;
                                             yyextra->current->startColumn = yyextra->yyColNr;
                                             yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1488,6 +1508,7 @@ NONLopt [^\n]*
                                         }
 <FindMembers>{B}*{TYPEDEFPREFIX}"struct{" |
 <FindMembers>{B}*{TYPEDEFPREFIX}"struct"/{BN}+ {
+                                          if (yyextra->insideJava) REJECT;
                                           QCString decl = yytext;
                                           yyextra->isTypedef=decl.find("typedef")!=-1;
                                           bool isConst=decl.find("const")!=-1;
@@ -1510,7 +1531,7 @@ NONLopt [^\n]*
                                             yyextra->current->type += " volatile";
                                           }
                                           yyextra->current->type += " struct" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1526,7 +1547,7 @@ NONLopt [^\n]*
                                           yyextra->current->spec    = Entry::Struct | Entry::Value;
                                           addType(yyscanner);
                                           yyextra->current->type += " value struct" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1542,7 +1563,7 @@ NONLopt [^\n]*
                                           yyextra->current->spec    = Entry::Struct | Entry::Ref;
                                           addType(yyscanner);
                                           yyextra->current->type += " ref struct" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1558,7 +1579,7 @@ NONLopt [^\n]*
                                           yyextra->current->spec    = Entry::Struct | Entry::Interface;
                                           addType(yyscanner);
                                           yyextra->current->type += " interface struct";
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1569,6 +1590,7 @@ NONLopt [^\n]*
                                         }
 <FindMembers>{B}*{TYPEDEFPREFIX}"union{" |
 <FindMembers>{B}*{TYPEDEFPREFIX}"union"{BN}+ {
+                                          if (yyextra->insideJava) REJECT;
                                           QCString decl=yytext;
                                           yyextra->isTypedef=decl.find("typedef")!=-1;
                                           bool isConst=decl.find("const")!=-1;
@@ -1587,7 +1609,7 @@ NONLopt [^\n]*
                                             yyextra->current->type += " volatile";
                                           }
                                           yyextra->current->type += " union" ;
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1622,7 +1644,7 @@ NONLopt [^\n]*
                                             yyextra->current->spec |= Entry::Strong;
                                             yyextra->current->spec |= Entry::EnumStruct;
                                           }
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1632,11 +1654,12 @@ NONLopt [^\n]*
                                           BEGIN( CompoundName ) ;
                                         }
 <FindMembers>{B}*"concept"{BN}+         { // C++20 concept
+                                          if (yyextra->insideJava) REJECT;
                                           yyextra->isTypedef=FALSE;
                                           yyextra->current->section = Entry::CONCEPT_SEC;
                                           addType(yyscanner);
                                           yyextra->current->type += " concept";
-                                          yyextra->current->fileName  = yyextra->yyFileName;
+                                          yyextra->current->fileName  = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
@@ -1682,6 +1705,7 @@ NONLopt [^\n]*
                                           BEGIN( ReadTempArgs );
                                         }
 <FindMembers>"namespace"{BN}+/{ID}{BN}*"=" { // namespace alias
+                                          if (yyextra->insideJava) REJECT;
                                           lineCount(yyscanner);
                                           BEGIN( NSAliasName );
                                         }
@@ -1707,7 +1731,7 @@ NONLopt [^\n]*
                                           lineCount(yyscanner);
                                           yyextra->current->name=removeRedundantWhiteSpace(substitute(yytext,"\\","::"));
                                           //printf("PHP: adding use relation: %s\n",qPrint(yyextra->current->name));
-                                          yyextra->current->fileName = yyextra->yyFileName;
+                                          yyextra->current->fileName = yyextra->fileName;
                                           // add a using declaration
                                           yyextra->current->section=Entry::USINGDECL_SEC;
                                           yyextra->current_root->copyToSubEntry(yyextra->current);
@@ -1746,7 +1770,7 @@ NONLopt [^\n]*
                                           lineCount(yyscanner);
                                           QCString scope=yytext;
                                           yyextra->current->name=removeRedundantWhiteSpace(substitute(scope.left(scope.length()-1),".","::"));
-                                          yyextra->current->fileName = yyextra->yyFileName;
+                                          yyextra->current->fileName = yyextra->fileName;
                                           yyextra->current->section=Entry::USINGDIR_SEC;
                                           yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
                                           initEntry(yyscanner);
@@ -1756,7 +1780,7 @@ NONLopt [^\n]*
                                           lineCount(yyscanner);
                                           QCString scope=yytext;
                                           yyextra->current->name=removeRedundantWhiteSpace(substitute(scope,".","::"));
-                                          yyextra->current->fileName = yyextra->yyFileName;
+                                          yyextra->current->fileName = yyextra->fileName;
                                           if (yyextra->insideD)
                                           {
                                             yyextra->current->section=Entry::USINGDIR_SEC;
@@ -1772,6 +1796,7 @@ NONLopt [^\n]*
                                           BEGIN(Using);
                                         }
 <FindMembers>"using"{BN}+               {
+                                          if (yyextra->insideJava) REJECT;
                                           yyextra->current->startLine=yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           lineCount(yyscanner);
@@ -1781,7 +1806,7 @@ NONLopt [^\n]*
 <Using>({ID}{BN}*("::"|"."){BN}*)*({ID}|{OPERATOR}) {
                                           lineCount(yyscanner);
                                           yyextra->current->name=yytext;
-                                          yyextra->current->fileName = yyextra->yyFileName;
+                                          yyextra->current->fileName = yyextra->fileName;
                                           yyextra->current->section=Entry::USINGDECL_SEC;
                                           yyextra->current->startLine = yyextra->yyLineNr;
                                           yyextra->previous = yyextra->current;
@@ -1793,7 +1818,7 @@ NONLopt [^\n]*
                                                          */
                                           {
                                             yyextra->current->name=yytext;
-                                            yyextra->current->fileName = yyextra->yyFileName;
+                                            yyextra->current->fileName = yyextra->fileName;
                                             yyextra->current->startLine = yyextra->yyLineNr;
                                             yyextra->current->startColumn = yyextra->yyColNr;
                                             yyextra->current->section=Entry::USINGDIR_SEC;
@@ -1860,7 +1885,7 @@ NONLopt [^\n]*
                                           BEGIN(UsingAlias);
                                         }
 <UsingDirective>{SCOPENAME}             { yyextra->current->name=removeRedundantWhiteSpace(yytext);
-                                          yyextra->current->fileName = yyextra->yyFileName;
+                                          yyextra->current->fileName = yyextra->fileName;
                                           yyextra->current->section=Entry::USINGDIR_SEC;
                                           yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
                                           initEntry(yyscanner);
@@ -2104,11 +2129,19 @@ NONLopt [^\n]*
                                           BEGIN(FindMembers);
                                         }
 <FindMembers>"requires"                 { // C++20 requires clause
+                                          if (yyextra->insideJava) REJECT;
                                           yyextra->current->req.resize(0);
                                           yyextra->requiresContext = YY_START;
                                           BEGIN(RequiresClause);
                                         }
+<RequiresClause>"requires"{BN}*/"{"     { // requires requires { ... }
+                                          if (yyextra->insideJava) REJECT;
+                                          lineCount(yyscanner) ;
+                                          yyextra->current->req+=yytext;
+                                          BEGIN( RequiresExpression ) ;
+                                        }
 <RequiresClause>"requires"{BN}*"("      { // requires requires(T x) { ... }
+                                          if (yyextra->insideJava) REJECT;
                                           lineCount(yyscanner) ;
                                           yyextra->current->req+=yytext;
                                           yyextra->lastRoundContext=RequiresExpression;
@@ -2125,7 +2158,7 @@ NONLopt [^\n]*
                                         }
 <RequiresExpression>\n                  {
                                           yyextra->current->req+=' ';
-                                          lineCount(yyextra);
+                                          lineCount(yyscanner);
                                         }
 <RequiresExpression>.                   {
                                           yyextra->current->req+=yytext;
@@ -2138,7 +2171,7 @@ NONLopt [^\n]*
                                           BEGIN( CopyRound ) ;
                                         }
 <RequiresClause>{ID}                    { // something like "requires true"
-                                          if (yyextra->current->req.stripWhiteSpace().isEmpty())
+                                          if (startOfRequiresExpression(yyextra->current->req))
                                           {
                                             yyextra->current->req=yytext;
                                             BEGIN(yyextra->requiresContext);
@@ -2149,18 +2182,32 @@ NONLopt [^\n]*
                                           }
                                         }
 <RequiresClause>{SCOPENAME}{BNopt}"("   { // "requires func(x)"
-                                          yyextra->current->req+=yytext;
-                                          yyextra->lastRoundContext=RequiresClause;
-                                          yyextra->pCopyRoundString=&yyextra->current->req;
-                                          yyextra->roundCount=0;
-                                          BEGIN( CopyRound );
+                                          if (startOfRequiresExpression(yyextra->current->req))
+                                          {
+                                            yyextra->current->req+=yytext;
+                                            yyextra->lastRoundContext=RequiresClause;
+                                            yyextra->pCopyRoundString=&yyextra->current->req;
+                                            yyextra->roundCount=0;
+                                            BEGIN( CopyRound );
+                                          }
+                                          else
+                                          {
+                                            REJECT;
+                                          }
                                         }
 <RequiresClause>{SCOPENAME}{BNopt}"<"   { // "requires C<S,T>"
-                                          yyextra->current->req+=yytext;
-                                          yyextra->lastSharpContext=RequiresClause;
-                                          yyextra->pCopySharpString=&yyextra->current->req;
-                                          yyextra->sharpCount=0;
-                                          BEGIN( CopySharp );
+                                          if (startOfRequiresExpression(yyextra->current->req))
+                                          {
+                                            yyextra->current->req+=yytext;
+                                            yyextra->lastSharpContext=RequiresClause;
+                                            yyextra->pCopySharpString=&yyextra->current->req;
+                                            yyextra->sharpCount=0;
+                                            BEGIN( CopySharp );
+                                          }
+                                          else
+                                          {
+                                            REJECT
+                                          }
                                         }
 <RequiresClause>"||"|"&&"             { // "requires A || B" or "requires A && B"
                                           yyextra->current->req+=yytext;
@@ -2311,6 +2358,18 @@ NONLopt [^\n]*
                                                 }
                                                 yyextra->current->name= yyextra->current->name.mid(7);
                                               }
+                                              else if (yyextra->current->name.left(10)=="constexpr ")
+                                              {
+                                                if (yyextra->current->type.isEmpty())
+                                                {
+                                                  yyextra->current->type="constexpr";
+                                                }
+                                                else
+                                                {
+                                                  yyextra->current->type+="constexpr ";
+                                                }
+                                                yyextra->current->name=yyextra->current->name.mid(10);
+                                              }
                                               else if (yyextra->current->name.left(6)=="const ")
                                               {
                                                 if (yyextra->current->type.isEmpty())
@@ -2335,6 +2394,18 @@ NONLopt [^\n]*
                                                 }
                                                 yyextra->current->name=yyextra->current->name.mid(9);
                                               }
+                                              else if (yyextra->current->name.left(8)=="typedef ")
+                                              {
+                                                if (yyextra->current->type.isEmpty())
+                                                {
+                                                  yyextra->current->type="typedef";
+                                                }
+                                                else
+                                                {
+                                                  yyextra->current->type+="typedef ";
+                                                }
+                                                yyextra->current->name=yyextra->current->name.mid(8);
+                                              }
                                             }
                                             QCString tmp=yytext;
                                             if (nameIsOperator(tmp))
@@ -2343,7 +2414,7 @@ NONLopt [^\n]*
                                             }
                                             else
                                             {
-                                              yyextra->externC=FALSE; // see bug759247
+                                              yyextra->externLinkage=FALSE; // see bug759247
                                               BEGIN(FindMembers);
                                             }
                                           }
@@ -2439,7 +2510,7 @@ NONLopt [^\n]*
                                           BEGIN( PreLineCtrl );
                                         }
 <PreLineCtrl>"\""[^\n\"]*"\""           {
-                                          yyextra->yyFileName = stripQuotes(yytext);
+                                          yyextra->fileName = stripQuotes(yytext);
                                           if (yyextra->lastPreLineCtrlContext==ReadBody ||
                                               yyextra->lastPreLineCtrlContext==ReadNSBody ||
                                               yyextra->lastPreLineCtrlContext==ReadBodyIntf)
@@ -2504,7 +2575,7 @@ NONLopt [^\n]*
                                         }
 <DefineEnd>\n                           {
                                           //printf("End define: doc=%s docFile=%s docLine=%d\n",qPrint(yyextra->current->doc),qPrint(yyextra->current->docFile),yyextra->current->docLine);
-                                          yyextra->current->fileName   = yyextra->yyFileName;
+                                          yyextra->current->fileName   = yyextra->fileName;
                                           yyextra->current->startLine  = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->type.resize(0);
@@ -2518,7 +2589,7 @@ NONLopt [^\n]*
                                         }
 <DefinePHPEnd>";"                       {
                                           //printf("End define\n");
-                                          yyextra->current->fileName   = yyextra->yyFileName;
+                                          yyextra->current->fileName   = yyextra->fileName;
                                           yyextra->current->startLine  = yyextra->yyLineNr;
                                           yyextra->current->startColumn = yyextra->yyColNr;
                                           yyextra->current->type.resize(0);
@@ -2641,7 +2712,7 @@ NONLopt [^\n]*
                                             BEGIN( DocBlock );
                                           }
                                         }
-<DefineEnd,FindFields,FindFieldArg,ReadInitializer,ReadInitializerPtr,OldStyleArgs>{BN}*{DCOMM}"<" {
+<DefineEnd,FindFields,ReadInitializer,ReadInitializerPtr,OldStyleArgs>{BN}*{DCOMM}"<" {
                                           if (yyextra->current->bodyLine==-1)
                                           {
                                             yyextra->current->bodyLine=yyextra->yyLineNr;
@@ -2674,12 +2745,12 @@ NONLopt [^\n]*
                                           if (yyextra->previous && yyextra->previous->section==Entry::GROUPDOC_SEC)
                                           {
                                             // link open command to the group defined in the yyextra->previous entry
-                                            yyextra->commentScanner.open(yyextra->previous.get(),yyextra->yyFileName,yyextra->yyLineNr);
+                                            yyextra->commentScanner.open(yyextra->previous.get(),yyextra->fileName,yyextra->yyLineNr);
                                           }
                                           else
                                           {
                                             // link open command to the yyextra->current entry
-                                            yyextra->commentScanner.open(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr);
+                                            yyextra->commentScanner.open(yyextra->current.get(),yyextra->fileName,yyextra->yyLineNr);
                                           }
                                           //yyextra->current = tmp;
                                           initEntry(yyscanner);
@@ -2723,7 +2794,7 @@ NONLopt [^\n]*
                                         }
 <FindMembers,FindFields,ReadInitializer,ReadInitializerPtr>{CPPC}([!/]){B}*{CMD}"}".*|{CCS}([!*]){B}*{CMD}"}"[^*]*{CCE}     {
                                           bool insideEnum = YY_START==FindFields || ((YY_START==ReadInitializer || YY_START==ReadInitializerPtr) && yyextra->lastInitializerContext==FindFields); // see bug746226
-                                          yyextra->commentScanner.close(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr,insideEnum);
+                                          yyextra->commentScanner.close(yyextra->current.get(),yyextra->fileName,yyextra->yyLineNr,insideEnum);
                                           lineCount(yyscanner);
                                         }
 <FindMembers>"=>"                       {
@@ -2781,7 +2852,7 @@ NONLopt [^\n]*
                                           //printf(">> initializer '%s' <<\n",qPrint(yyextra->current->initializer));
                                           if (*yytext==';' && (yyextra->current_root->spec&Entry::Enum))
                                           {
-                                            yyextra->current->fileName   = yyextra->yyFileName;
+                                            yyextra->current->fileName   = yyextra->fileName;
                                             yyextra->current->startLine  = yyextra->yyLineNr;
                                             yyextra->current->startColumn = yyextra->yyColNr;
                                             yyextra->current->args       = yyextra->current->args.simplifyWhiteSpace();
@@ -3378,7 +3449,8 @@ NONLopt [^\n]*
                                           }
                                           bool stat = yyextra->current->stat;
                                           Protection prot = yyextra->current->protection;
-                                          if (yyextra->current->section==Entry::CONCEPT_SEC) // C++20 concept
+                                          bool isConcept = yyextra->current->section==Entry::CONCEPT_SEC;
+                                          if (isConcept) // C++20 concept
                                           {
                                             yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ;
                                             initEntry(yyscanner);
@@ -3393,7 +3465,7 @@ NONLopt [^\n]*
                                                 yyextra->current->spec = 0;
                                             }
                                             yyextra->current->section = Entry::VARIABLE_SEC ;
-                                            yyextra->current->fileName = yyextra->yyFileName;
+                                            yyextra->current->fileName = yyextra->fileName;
                                             yyextra->current->startLine = yyextra->yyBegLineNr;
                                             yyextra->current->startColumn = yyextra->yyBegColNr;
                                             yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ;
@@ -3466,7 +3538,7 @@ NONLopt [^\n]*
                                           {
                                             yyextra->current->args += yytext ;
                                             yyextra->squareCount=1;
-                                            yyextra->externC=FALSE; // see bug759247
+                                            yyextra->externLinkage=FALSE; // see bug759247
                                             BEGIN( Array ) ;
                                           }
                                         }
@@ -3628,7 +3700,7 @@ NONLopt [^\n]*
                                           // the parameter name for the property - just skip.
                                         }
 <IDLProp>";"                            {
-                                          yyextra->current->fileName   = yyextra->yyFileName;
+                                          yyextra->current->fileName   = yyextra->fileName;
                                           yyextra->current->type                = yyextra->idlProp;
                                           yyextra->current->args       = yyextra->current->args.simplifyWhiteSpace();
                                           if (!yyextra->current->args.isEmpty())
@@ -3689,9 +3761,9 @@ NONLopt [^\n]*
                                           yyextra->current->bodyColumn = yyextra->yyColNr;
                                           yyextra->current->name     = yytext;
                                         }
-<FindFields>"("                         {
+<FindFields>[({]                        {
                                           // Java enum initializer
-                                          unput('(');
+                                          unput(*yytext);
                                           yyextra->lastInitializerContext = YY_START;
                                           yyextra->initBracketCount=0;
                                           yyextra->current->initializer.str("=");
@@ -3708,7 +3780,7 @@ NONLopt [^\n]*
                                           {
                                             if (!yyextra->current->name.isEmpty())
                                             {
-                                              yyextra->current->fileName   = yyextra->yyFileName;
+                                              yyextra->current->fileName   = yyextra->fileName;
                                               yyextra->current->startLine  = yyextra->yyLineNr;
                                               yyextra->current->startColumn = yyextra->yyColNr;
                                               if (!(yyextra->current_root->spec&Entry::Enum))
@@ -3729,17 +3801,13 @@ NONLopt [^\n]*
                                             REJECT;
                                           }
                                         }
-<SkipRemainder>\n                       {
-                                          lineCount(yyscanner);
-                                        }
-<SkipRemainder>[^\n]*
 <FindFields>","                         {
                                           //printf("adding '%s' '%s' '%s' to enum '%s' (mGrpId=%d)\n",
                                           //     qPrint(yyextra->current->type), qPrint(yyextra->current->name),
                                           //     qPrint(yyextra->current->args), qPrint(yyextra->current_root->name),yyextra->current->mGrpId);
                                           if (!yyextra->current->name.isEmpty())
                                           {
-                                            yyextra->current->fileName   = yyextra->yyFileName;
+                                            yyextra->current->fileName   = yyextra->fileName;
                                             yyextra->current->startLine  = yyextra->yyLineNr;
                                             yyextra->current->startColumn = yyextra->yyColNr;
                                             if (!(yyextra->current_root->spec&Entry::Enum))
@@ -3774,9 +3842,6 @@ NONLopt [^\n]*
                                           yyextra->lastSquareContext = YY_START;
                                           BEGIN(SkipSquare);
                                         }
-  /*
-<FindFieldArg>","                       { unput(*yytext); BEGIN(FindFields); }
-  */
 <ReadBody,ReadNSBody,ReadBodyIntf>[^\r\n\#{}"@'/<]*     { yyextra->current->program << yytext ; }
 <ReadBody,ReadNSBody,ReadBodyIntf>{CPPC}.*                { yyextra->current->program << yytext ; }
 <ReadBody,ReadNSBody,ReadBodyIntf>"#".* { if (!yyextra->insidePHP)
@@ -3806,11 +3871,12 @@ NONLopt [^\n]*
                                           yyextra->lastStringContext=YY_START;
                                           BEGIN( CopyGString );
                                         }
-<ReadBody,ReadNSBody,ReadBodyIntf>{CCS}{B}*              { yyextra->current->program << yytext ;
+<ReadBody,ReadNSBody,ReadBodyIntf>{DCOMMC}  { yyextra->doxygenComment=true; REJECT;}
+<ReadBody,ReadNSBody,ReadBodyIntf>{CCS}{B}* { yyextra->current->program << yytext ;
                                           yyextra->lastContext = YY_START ;
                                           BEGIN( Comment ) ;
                                         }
-<ReadBody,ReadNSBody,ReadBodyIntf>{CCS}{BL}              { yyextra->current->program << yytext ;
+<ReadBody,ReadNSBody,ReadBodyIntf>{CCS}{BL} { yyextra->current->program << yytext ;
                                           ++yyextra->yyLineNr ;
                                           yyextra->lastContext = YY_START ;
                                           BEGIN( Comment ) ;
@@ -4128,7 +4194,7 @@ NONLopt [^\n]*
                                               {
                                                 varEntry->type+=yyextra->current->name+yyextra->msType;
                                               }
-                                              varEntry->fileName = yyextra->yyFileName;
+                                              varEntry->fileName = yyextra->fileName;
                                               varEntry->startLine = yyextra->yyLineNr;
                                               varEntry->startColumn = yyextra->yyColNr;
                                               varEntry->doc = yyextra->current->doc;
@@ -4240,7 +4306,7 @@ NONLopt [^\n]*
                                           }
                                         }
 <FuncPtr>.                              {
-                                          //printf("error: FuncPtr '%c' unexpected at line %d of %s\n",*yytext,yyextra->yyLineNr,yyextra->yyFileName);
+                                          //printf("error: FuncPtr '%c' unexpected at line %d of %s\n",*yytext,yyextra->yyLineNr,yyextra->fileName);
                                         }
 <FuncPtrOperator>"("{BN}*")"{BNopt}/"(" {
                                           yyextra->current->name += yytext;
@@ -4560,7 +4626,7 @@ NONLopt [^\n]*
                                           yyextra->fullArgString+=yytext;
                                           BEGIN(CopyArgVerbatim);
                                         }
-<CopyArgCommentLine>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-]   { // verbatim command (which could contain nested comments!)
+<CopyArgCommentLine>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-]   { // verbatim command (which could contain nested comments!)
                                           yyextra->docBlockName=&yytext[1];
                                           yyextra->fullArgString+=yytext;
                                           BEGIN(CopyArgVerbatim);
@@ -4582,7 +4648,7 @@ NONLopt [^\n]*
                                           yyextra->fullArgString+=yytext;
                                           BEGIN(CopyArgVerbatim);
                                         }
-<CopyArgVerbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"ebdmsc"|"enduml"|"endcode"|"f$"|"f]"|"f}"|"f)")/[^a-z_A-Z0-9\-] { // end of verbatim block
+<CopyArgVerbatim>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode"|"f$"|"f]"|"f}"|"f)")/[^a-z_A-Z0-9\-] { // end of verbatim block
                                           yyextra->fullArgString+=yytext;
                                          if (yytext[1]=='f' && yyextra->docBlockName==&yytext[1])
                                           {
@@ -4598,7 +4664,7 @@ NONLopt [^\n]*
 <CopyArgComment,CopyArgVerbatim>\n      { yyextra->fullArgString+=*yytext; lineCount(yyscanner); }
 <CopyArgComment,CopyArgVerbatim>.       { yyextra->fullArgString+=*yytext; }
 <CopyArgComment>{CMD}("brief"|"short"){B}+ {
-                                          warn(yyextra->yyFileName,yyextra->yyLineNr,
+                                          warn(yyextra->fileName,yyextra->yyLineNr,
                                               "Ignoring %cbrief command inside argument documentation",*yytext
                                              );
                                           yyextra->fullArgString+=' ';
@@ -4841,6 +4907,7 @@ NONLopt [^\n]*
                                           BEGIN(FuncQual);
                                         }
 <TrailingReturn>"requires"{BN}+         {
+                                          if (yyextra->insideJava) REJECT;
                                           yyextra->requiresContext = FuncQual;
                                           yyextra->current->req+=' ';
                                           BEGIN(RequiresClause);
@@ -4857,7 +4924,7 @@ NONLopt [^\n]*
                                           }
                                           else
                                           {
-                                            warn(yyextra->yyFileName,yyextra->yyLineNr,
+                                            warn(yyextra->fileName,yyextra->yyLineNr,
                                                  "Found ')' without opening '(' for trailing return type '%s)...'",
                                                  qPrint(yyextra->current->argList.trailingReturnType()));
                                           }
@@ -4913,45 +4980,6 @@ NONLopt [^\n]*
                                         }
 <CliOverride>.                          {
                                         }
-<FuncPtrInit>[{;]                       {
-                                          unput(*yytext);
-                                          BEGIN(FuncQual);
-                                        }
-<FuncPtrInit>\"                         {
-                                          yyextra->current->args += *yytext;
-                                          yyextra->pCopyQuotedString=&yyextra->current->args;
-                                          yyextra->lastStringContext=FuncPtrInit;
-                                          BEGIN(CopyString);
-                                        }
-<FuncPtrInit>\'                         {
-                                          yyextra->current->args += *yytext;
-                                          if (yyextra->insidePHP)
-                                          {
-                                            yyextra->pCopyQuotedString=&yyextra->current->args;
-                                            yyextra->lastStringContext=FuncPtrInit;
-                                            BEGIN(CopyPHPString);
-                                          }
-                                        }
-<FuncPtrInit>{CHARLIT}                  {
-                                          if (yyextra->insidePHP)
-                                          {
-                                            REJECT;
-                                          }
-                                          else
-                                          {
-                                            yyextra->current->args += yytext;
-                                          }
-                                        }
-<FuncPtrInit>{ID}                       {
-                                          yyextra->current->args += yytext;
-                                        }
-<FuncPtrInit>.                          {
-                                          yyextra->current->args += *yytext;
-                                        }
-<FuncPtrInit>\n                         {
-                                          yyextra->current->args += *yytext;
-                                          lineCount(yyscanner);
-                                        }
 <FuncQual>{ID}                          {
                                           if (yyextra->insideCpp && qstrcmp(yytext,"requires")==0)
                                           {
@@ -5076,7 +5104,7 @@ NONLopt [^\n]*
                                           yyextra->current->name=removeRedundantWhiteSpace(yyextra->current->name);
                                           yyextra->current->type=removeRedundantWhiteSpace(yyextra->current->type);
                                           yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args);
-                                          yyextra->current->fileName = yyextra->yyFileName;
+                                          yyextra->current->fileName = yyextra->fileName;
                                           yyextra->current->startLine = yyextra->yyBegLineNr;
                                           yyextra->current->startColumn = yyextra->yyBegColNr;
                                           static const reg::Ex re(R"(\([^)]*[*&][^)]*\))");
@@ -5382,7 +5410,7 @@ NONLopt [^\n]*
                                           BEGIN( SkipString );
                                         }
 <SkipInits>;                            {
-                                          warn(yyextra->yyFileName,yyextra->yyLineNr,
+                                          warn(yyextra->fileName,yyextra->yyLineNr,
                                               "Found ';' while parsing initializer list! "
                                               "(doxygen could be confused by a macro call without semicolon)"
                                              );
@@ -5424,6 +5452,7 @@ NONLopt [^\n]*
 <SkipString,SkipPHPString>\n            {
                                           lineCount(yyscanner);
                                         }
+<SkipString>"[["                        { }
 <SkipString,SkipPHPString>.             { }
 <CompoundName>":"                       { // for "class : public base {} var;" construct, see bug 608359
                                           unput(':');
@@ -5885,7 +5914,6 @@ NONLopt [^\n]*
                                           }
                                         }
 <ClassVar>[;=*&]                        {
-                                          unput(*yytext);
                                           if (yyextra->isTypedef) // typedef of a class, put typedef keyword back
                                           {
                                             yyextra->current->type.prepend("typedef");
@@ -5895,6 +5923,15 @@ NONLopt [^\n]*
                                           { // found "enum a *b" -> variable
                                             yyextra->current->section = Entry::VARIABLE_SEC ;
                                           }
+                                          if (yytext[0]==';' && yyextra->current->section == Entry::ENUM_SEC)
+                                          {
+                                            yyextra->current->reset();
+                                            initEntry(yyscanner);
+                                          }
+                                          else
+                                          {
+                                            unput(*yytext);
+                                          }
                                           BEGIN( FindMembers );
                                         }
 <Bases,ClassVar>{CPPC}"/"/[^/]              {
@@ -5906,7 +5943,7 @@ NONLopt [^\n]*
                                           {
                                             lineCount(yyscanner);
                                             yyextra->current->program << yytext;
-                                            yyextra->current->fileName = yyextra->yyFileName ;
+                                            yyextra->current->fileName = yyextra->fileName ;
                                             yyextra->current->startLine = yyextra->yyLineNr ;
                                             yyextra->current->startColumn = yyextra->yyColNr;
                                             yyextra->curlyCount=0;
@@ -5925,7 +5962,7 @@ NONLopt [^\n]*
                                           {
                                             lineCount(yyscanner);
                                             yyextra->current->program << yytext;
-                                            yyextra->current->fileName = yyextra->yyFileName ;
+                                            yyextra->current->fileName = yyextra->fileName ;
                                             yyextra->current->startLine = yyextra->yyLineNr ;
                                             yyextra->current->startColumn = yyextra->yyColNr;
                                             yyextra->curlyCount=0;
@@ -5934,7 +5971,7 @@ NONLopt [^\n]*
                                         }
 <CompoundName,ClassVar>{B}*"{"{B}*      {
                                           yyextra->current->program.str(std::string());
-                                          yyextra->current->fileName = yyextra->yyFileName ;
+                                          yyextra->current->fileName = yyextra->fileName ;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
                                           yyextra->current->bodyColumn = yyextra->yyColNr;
                                           yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name);
@@ -6187,7 +6224,7 @@ NONLopt [^\n]*
                                         }
 <Bases>{B}*"{"{B}*                      {
                                           yyextra->current->program.str(std::string());
-                                          yyextra->current->fileName = yyextra->yyFileName ;
+                                          yyextra->current->fileName = yyextra->fileName ;
                                           yyextra->current->bodyLine  = yyextra->yyLineNr;
                                           yyextra->current->bodyColumn = yyextra->yyColNr;
                                           yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name);
@@ -6221,17 +6258,21 @@ NONLopt [^\n]*
                                         }
 <Comment>{CCS}                           { yyextra->current->program << yytext ; }
 <Comment>{CPPC}                           { yyextra->current->program << yytext ; }
-<Comment>{CMD}("code"|"verbatim")       {
-                                          yyextra->insideCode=TRUE;
+<Comment>{CMD}("code"|"verbatim"|"iliteral") {
+                                          if (yyextra->doxygenComment) yyextra->insideCode=TRUE;
                                           yyextra->current->program << yytext ;
                                         }
-<Comment>{CMD}("endcode"|"endverbatim") {
-                                          yyextra->insideCode=FALSE;
+<Comment>{CMD}("endcode"|"endverbatim"|"endiliteral") {
+                                          if (yyextra->doxygenComment) yyextra->insideCode=FALSE;
                                           yyextra->current->program << yytext ;
                                         }
 <Comment>[^ \.\t\r\n\/\*]+              { yyextra->current->program << yytext ; }
-<Comment>{CCE}                           { yyextra->current->program << yytext ;
-                                          if (!yyextra->insideCode) BEGIN( yyextra->lastContext ) ;
+<Comment>{CCE}                          { yyextra->current->program << yytext ;
+                                          if (!yyextra->insideCode)
+                                          {
+                                            yyextra->doxygenComment=false;
+                                            BEGIN( yyextra->lastContext );
+                                          }
                                         }
 <Comment>.                              { yyextra->current->program << *yytext ; }
 
@@ -6244,7 +6285,7 @@ NONLopt [^\n]*
                                           else
                                           {
                                             yyextra->current->docLine = yyextra->yyLineNr;
-                                            yyextra->current->docFile = yyextra->yyFileName;
+                                            yyextra->current->docFile = yyextra->fileName;
                                           }
 
                                           yyextra->lastDocContext = YY_START;
@@ -6263,7 +6304,7 @@ NONLopt [^\n]*
                                           if (yyextra->docBlockAutoBrief)
                                           {
                                             yyextra->current->briefLine = yyextra->yyLineNr;
-                                            yyextra->current->briefFile = yyextra->yyFileName;
+                                            yyextra->current->briefFile = yyextra->fileName;
                                           }
                                           startCommentBlock(yyscanner,FALSE);
                                           BEGIN( DocBlock );
@@ -6276,13 +6317,13 @@ NONLopt [^\n]*
                                           {
                                             yyextra->lastDocContext = YY_START;
 
-                                            //printf("Found comment banner at %s:%d\n",yyextra->yyFileName,yyextra->yyLineNr);
+                                            //printf("Found comment banner at %s:%d\n",yyextra->fileName,yyextra->yyLineNr);
                                             if (yyextra->current_root->section & Entry::SCOPE_MASK)
                                             {
                                               yyextra->current->inside = yyextra->current_root->name+"::";
                                             }
                                             yyextra->current->docLine = yyextra->yyLineNr;
-                                            yyextra->current->docFile = yyextra->yyFileName;
+                                            yyextra->current->docFile = yyextra->fileName;
                                             yyextra->docBlockContext = YY_START;
                                             yyextra->docBlockInBody  = YY_START==SkipCurly;
                                             bool javadocAutoBrief = Config_getBool(JAVADOC_AUTOBRIEF);
@@ -6295,7 +6336,7 @@ NONLopt [^\n]*
                                             if (yyextra->docBlockAutoBrief)
                                             {
                                               yyextra->current->briefLine = yyextra->yyLineNr;
-                                              yyextra->current->briefFile = yyextra->yyFileName;
+                                              yyextra->current->briefFile = yyextra->fileName;
                                             }
                                             startCommentBlock(yyscanner,FALSE);
                                             BEGIN( DocBlock );
@@ -6304,19 +6345,20 @@ NONLopt [^\n]*
                                           {
                                             yyextra->current->program << yytext ;
                                             yyextra->lastContext = YY_START ;
+                                            yyextra->doxygenComment=true;
                                             BEGIN( Comment ) ;
                                           }
                                         }
 <FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>({CPPC}{B}*)?{CCS}"*"/{NCOMM} {
                                           yyextra->lastDocContext = YY_START;
 
-                                          //printf("Found comment block at %s:%d\n",yyextra->yyFileName,yyextra->yyLineNr);
+                                          //printf("Found comment block at %s:%d\n",yyextra->fileName,yyextra->yyLineNr);
                                           if (yyextra->current_root->section & Entry::SCOPE_MASK)
                                           {
                                             yyextra->current->inside = yyextra->current_root->name+"::";
                                           }
                                           yyextra->current->docLine = yyextra->yyLineNr;
-                                          yyextra->current->docFile = yyextra->yyFileName;
+                                          yyextra->current->docFile = yyextra->fileName;
                                           yyextra->docBlockContext = YY_START;
                                           yyextra->docBlockInBody  = YY_START==SkipCurly;
                                           bool javadocAutoBrief = Config_getBool(JAVADOC_AUTOBRIEF);
@@ -6329,7 +6371,7 @@ NONLopt [^\n]*
                                           if (yyextra->docBlockAutoBrief)
                                           {
                                             yyextra->current->briefLine = yyextra->yyLineNr;
-                                            yyextra->current->briefFile = yyextra->yyFileName;
+                                            yyextra->current->briefFile = yyextra->fileName;
                                           }
                                           startCommentBlock(yyscanner,FALSE);
                                           BEGIN( DocBlock );
@@ -6366,14 +6408,14 @@ NONLopt [^\n]*
                                           startCommentBlock(yyscanner,yyextra->current->brief.isEmpty());
                                           BEGIN( DocLine );
                                         }
-<FindMembers>"extern"{BN}*"\"C"("++")?"\""{BN}*("{")?  {
+<FindMembers>"extern"{BN}*"\""[^\"]+"\""{BN}*("{")?  {
                                           lineCount(yyscanner);
-                                          yyextra->externC=TRUE;
+                                          yyextra->externLinkage=TRUE;
                                         }
 <FindMembers>"{"                        {
-                                          if (yyextra->externC)
+                                          if (yyextra->externLinkage)
                                           {
-                                            yyextra->externC=FALSE;
+                                            yyextra->externLinkage=FALSE;
                                           }
                                           else if (yyextra->insideCS &&
                                               !yyextra->current->name.isEmpty() &&
@@ -6629,7 +6671,7 @@ NONLopt [^\n]*
                                           yyextra->nestedComment=FALSE;
                                           BEGIN(DocCopyBlock);
                                         }
-<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-]     { // verbatim command (which could contain nested comments!)
+<DocBlock>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-]     { // verbatim command (which could contain nested comments!)
                                           yyextra->docBlock << yytext;
                                           yyextra->docBlockName=&yytext[1];
                                           yyextra->fencedSize=0;
@@ -6645,7 +6687,9 @@ NONLopt [^\n]*
                                           yyextra->nestedComment=FALSE;
                                           BEGIN(DocCopyBlock);
                                         }
-<DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]*                {
+<DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]*/(".")?[a-zA-Z0-9#_-]+ |
+<DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]*/"{"[^}]+"}" |
+<DocBlock>^({B}*"*"+)?{B}{0,3}"```"[`]* {
                                           QCString pat = substitute(yytext,"*"," ");
                                           yyextra->docBlock << pat;
                                           yyextra->docBlockName="```";
@@ -6700,7 +6744,7 @@ NONLopt [^\n]*
                                             BEGIN(DocBlock);
                                           }
                                         }
-<DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block
+<DocCopyBlock>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block
                                           yyextra->docBlock << yytext;
                                           if (&yytext[4]==yyextra->docBlockName)
                                           {
@@ -6708,11 +6752,7 @@ NONLopt [^\n]*
                                           }
                                         }
 <DocCopyBlock>^{B}*"*"+/{BN}+           { // start of a comment line
-                                          if (yyextra->docBlockName=="verbatim")
-                                          {
-                                            REJECT;
-                                          }
-                                          else if (yyextra->docBlockName=="code")
+                                          if ((yyextra->docBlockName=="verbatim") | (yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral"))
                                           {
                                             REJECT;
                                           }
@@ -6724,7 +6764,7 @@ NONLopt [^\n]*
                                           }
                                         }
 <DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}*    { // start of a comment line with two *'s
-                                          if (yyextra->docBlockName=="code")
+                                          if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral"))
                                           {
                                             QCString indent;
                                             indent.fill(' ',computeIndent(yytext,0));
@@ -6736,7 +6776,7 @@ NONLopt [^\n]*
                                           }
                                         }
 <DocCopyBlock>^{B}*"*"+/({ID}|"(")      { // Assume *var or *(... is part of source code (see bug723516)
-                                          if (yyextra->docBlockName=="code")
+                                          if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral"))
                                           {
                                             QCString indent;
                                             indent.fill(' ',computeIndent(yytext,-1));
@@ -6748,7 +6788,7 @@ NONLopt [^\n]*
                                           }
                                         }
 <DocCopyBlock>^{B}*"*"+/{BN}*           { // start of a comment line with one *
-                                          if (yyextra->docBlockName=="code")
+                                          if ((yyextra->docBlockName=="code") || (yyextra->docBlockName=="iliteral"))
                                           {
                                             QCString indent;
                                             if (yyextra->nestedComment) // keep * it is part of the code
@@ -6805,7 +6845,7 @@ NONLopt [^\n]*
                                           yyextra->docBlock << *yytext;
                                         }
 <DocCopyBlock><<EOF>>                   {
-                                          warn(yyextra->yyFileName,yyextra->yyLineNr,
+                                          warn(yyextra->fileName,yyextra->yyLineNr,
                                               "reached end of file while inside a '%s' block!\n"
                                               "The command that should end the block seems to be missing!\n",
                                               qPrint(yyextra->docBlockName));
@@ -6924,6 +6964,18 @@ NONLopt [^\n]*
                                             BEGIN(EndCppQuote);
                                           }
                                         }
+<*>^{B}*"#"                             {
+                                          if (!yyextra->insidePHP)
+                                          {
+                                            yyextra->lastCPPContext = YY_START;
+                                            BEGIN( SkipCPP ) ;
+                                          }
+                                          else
+                                          {
+                                            yyextra->lastCContext = YY_START ;
+                                            BEGIN( SkipCxxComment ) ;
+                                          }
+                                        }
 <*>"#"                                  {
                                           if (!yyextra->insidePHP)
                                             REJECT;
@@ -6945,7 +6997,7 @@ NONLopt [^\n]*
                                           }
                                         }
 <*>\?                                   {
-                                          if (yyextra->insideCS && (YY_START != SkipRound))
+                                          if (yyextra->insideCS && (YY_START != SkipRound) && (YY_START != CSAccessorDecl))
                                           {
                                             if (yyextra->current->type.isEmpty())
                                             {
@@ -7104,6 +7156,16 @@ static QCString stripQuotes(const char *s)
 
 //-----------------------------------------------------------------
 
+// return TRUE iff req holds the start of a requires expression
+// or sub-expression without parenthesis, i.e. req is empty or ends with || or &&
+static bool startOfRequiresExpression(const QCString &req)
+{
+  QCString r = req.stripWhiteSpace();
+  return r.isEmpty() || r.endsWith("&&") || r.endsWith("||");
+}
+
+//-----------------------------------------------------------------
+
 static bool nameIsOperator(QCString &name)
 {
   int i=name.find("operator");
@@ -7118,7 +7180,7 @@ static bool nameIsOperator(QCString &name)
 static void setContext(yyscan_t yyscanner)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
-  yyextra->language    = getLanguageFromFileName(yyextra->yyFileName);
+  yyextra->language    = getLanguageFromFileName(yyextra->fileName);
   yyextra->insideIDL   = yyextra->language==SrcLangExt_IDL;
   yyextra->insideJava  = yyextra->language==SrcLangExt_Java;
   yyextra->insideCS    = yyextra->language==SrcLangExt_CSharp;
@@ -7131,7 +7193,7 @@ static void setContext(yyscan_t yyscanner)
                           yyextra->language==SrcLangExt_Lex);
   //printf("setContext(%s) yyextra->insideIDL=%d yyextra->insideJava=%d yyextra->insideCS=%d "
   //       "yyextra->insideD=%d yyextra->insidePHP=%d yyextra->insideObjC=%d\n",
-  //       qPrint(yyextra->yyFileName),yyextra->insideIDL,yyextra->insideJava,yyextra->insideCS,yyextra->insideD,yyextra->insidePHP,yyextra->insideObjC
+  //       qPrint(yyextra->fileName),yyextra->insideIDL,yyextra->insideJava,yyextra->insideCS,yyextra->insideD,yyextra->insidePHP,yyextra->insideObjC
   //    );
 }
 
@@ -7158,7 +7220,7 @@ static void prependScope(yyscan_t yyscanner)
 static bool checkForKnRstyleC(yyscan_t yyscanner)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
-  if (((QCString)yyextra->yyFileName).right(2).lower()!=".c") return FALSE; // must be a C file
+  if (((QCString)yyextra->fileName).right(2).lower()!=".c") return FALSE; // must be a C file
   if (yyextra->current->argList.empty()) return FALSE; // must have arguments
   for (const Argument &a : yyextra->current->argList)
   {
@@ -7311,12 +7373,12 @@ static void startCommentBlock(yyscan_t yyscanner,bool brief)
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   if (brief)
   {
-    yyextra->current->briefFile = yyextra->yyFileName;
+    yyextra->current->briefFile = yyextra->fileName;
     yyextra->current->briefLine = yyextra->yyLineNr;
   }
   else
   {
-    yyextra->current->docFile = yyextra->yyFileName;
+    yyextra->current->docFile = yyextra->fileName;
     yyextra->current->docLine = yyextra->yyLineNr;
   }
 }
@@ -7355,20 +7417,20 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief
   std::shared_ptr<Entry> docEntry = yyextra->docBlockInBody && yyextra->previous ? yyextra->previous : yyextra->current;
   if (yyextra->docBlockInBody && docEntry && docEntry->inbodyLine==-1)
   {
-    docEntry->inbodyFile = yyextra->yyFileName;
+    docEntry->inbodyFile = yyextra->fileName;
     docEntry->inbodyLine = lineNr;
   }
 
   int position=0;
   bool needsEntry=FALSE;
-  Markdown markdown(yyextra->yyFileName,lineNr);
+  Markdown markdown(yyextra->fileName,lineNr);
   QCString strippedDoc = stripIndentation(doc);
   QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(strippedDoc,lineNr) : strippedDoc;
   while (yyextra->commentScanner.parseCommentBlock(
         yyextra->thisParser,
         yyextra->docBlockInBody && yyextra->previous ? yyextra->previous.get() : yyextra->current.get(),
         processedDoc, // text
-        yyextra->yyFileName,   // file
+        yyextra->fileName,   // file
         lineNr,       // line of block start
         yyextra->docBlockInBody ? FALSE : brief,               // isBrief
         yyextra->docBlockInBody ? FALSE : yyextra->docBlockAutoBrief,   // isJavaDocStyle
@@ -7428,7 +7490,7 @@ static void handleParametersCommentBlocks(yyscan_t yyscanner,ArgumentList &al)
              yyextra->thisParser,
              yyextra->current.get(),
              a.docs,             // text
-             yyextra->yyFileName,         // file
+             yyextra->fileName,         // file
              yyextra->current->docLine,   // line of block start
              FALSE,
              FALSE,
@@ -7483,7 +7545,7 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt)
       else
         BEGIN( FindMembers ) ;
       yyextra->current_root = ce;
-      yyextra->yyFileName = ce->fileName;
+      yyextra->fileName = ce->fileName;
       //setContext();
       yyextra->yyLineNr = ce->bodyLine;
       yyextra->yyColNr = ce->bodyColumn;
@@ -7552,13 +7614,13 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt)
       //memberGroupRelates.resize(0);
       //memberGroupInside.resize(0);
       QCString name = ce->name;
-      yyextra->commentScanner.enterCompound(yyextra->yyFileName,yyextra->yyLineNr,name);
+      yyextra->commentScanner.enterCompound(yyextra->fileName,yyextra->yyLineNr,name);
 
       scannerYYlex(yyscanner);
       yyextra->lexInit=TRUE;
       //forceEndGroup();
 
-      yyextra->commentScanner.leaveCompound(yyextra->yyFileName,yyextra->yyLineNr,name);
+      yyextra->commentScanner.leaveCompound(yyextra->fileName,yyextra->yyLineNr,name);
 
       yyextra->programStr.resize(0);
       ce->program.str(std::string());
@@ -7566,7 +7628,7 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt)
 
       //if (depthIf>0)
       //{
-      //        warn(yyextra->yyFileName,yyextra->yyLineNr,"Documentation block ended in the middle of a conditional section!");
+      //        warn(yyextra->fileName,yyextra->yyLineNr,"Documentation block ended in the middle of a conditional section!");
       //}
     }
     parseCompounds(yyscanner,ce);
@@ -7598,21 +7660,21 @@ static void parseMain(yyscan_t yyscanner,
   yyextra->yyLineNr      = 1 ;
   yyextra->yyBegLineNr   = 1;
   yyextra->yyBegColNr    = 0;
-  yyextra->yyFileName = fileName;
+  yyextra->fileName = fileName;
   yyextra->clangParser = clangParser;
   setContext(yyscanner);
   rt->lang = yyextra->language;
-  msg("Parsing file %s...\n",qPrint(yyextra->yyFileName));
+  msg("Parsing file %s...\n",qPrint(yyextra->fileName));
 
   yyextra->current_root  = rt;
   initParser(yyscanner);
-  yyextra->commentScanner.enterFile(yyextra->yyFileName,yyextra->yyLineNr);
+  yyextra->commentScanner.enterFile(yyextra->fileName,yyextra->yyLineNr);
   yyextra->current = std::make_shared<Entry>();
   //printf("yyextra->current=%p yyextra->current_root=%p\n",yyextra->current,yyextra->current_root);
-  int sec=guessSection(yyextra->yyFileName);
+  int sec=guessSection(yyextra->fileName);
   if (sec)
   {
-    yyextra->current->name    = yyextra->yyFileName;
+    yyextra->current->name    = yyextra->fileName;
     yyextra->current->section = sec;
     yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
   }
@@ -7625,7 +7687,7 @@ static void parseMain(yyscan_t yyscanner,
   else if ( yyextra->insideJava ) // add default java.lang package scope
   {
     yyextra->current->name="java::lang"; // '::' is used in doxygen's internal representation as a scope separator
-    yyextra->current->fileName = yyextra->yyFileName;
+    yyextra->current->fileName = yyextra->fileName;
     yyextra->current->section=Entry::USINGDIR_SEC;
     yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
     initEntry(yyscanner);
@@ -7641,11 +7703,11 @@ static void parseMain(yyscan_t yyscanner,
 
   if (YY_START==Comment)
   {
-    warn(yyextra->yyFileName,yyextra->yyLineNr,"File ended in the middle of a comment block! Perhaps a missing \\endcode?");
+    warn(yyextra->fileName,yyextra->yyLineNr,"File ended in the middle of a comment block! Perhaps a missing \\endcode?");
   }
 
   //forceEndGroup();
-  yyextra->commentScanner.leaveFile(yyextra->yyFileName,yyextra->yyLineNr);
+  yyextra->commentScanner.leaveFile(yyextra->fileName,yyextra->yyLineNr);
 
   yyextra->programStr.resize(0);
   rt->program.str(std::string());
@@ -7672,7 +7734,7 @@ static void parsePrototype(yyscan_t yyscanner,const QCString &text)
   //printf("**** parsePrototype(%s) begin\n",qPrint(text));
   if (text.isEmpty())
   {
-    warn(yyextra->yyFileName,yyextra->yyLineNr,"Empty prototype found!");
+    warn(yyextra->fileName,yyextra->yyLineNr,"Empty prototype found!");
     return;
   }
   if (!yyextra->current) // nothing to store (see bug683516)
index 0fda0fb..55716e0 100644 (file)
@@ -472,7 +472,7 @@ void SearchIndexExternal::setCurrentDoc(const Definition *ctx,const QCString &an
 {
   static QCString extId = stripPath(Config_getString(EXTERNAL_SEARCH_ID));
   QCString baseName = isSourceFile ? (toFileDef(ctx))->getSourceFileBase() : ctx->getOutputFileBase();
-  QCString url = baseName + Doxygen::htmlFileExtension;
+  QCString url = addHtmlExtensionIfMissing(baseName);
   if (!anchor.isEmpty()) url+=QCString("#")+anchor;
   QCString key = extId+";"+url;
 
index c219677..0cee070 100644 (file)
@@ -78,6 +78,9 @@ class SectionInfo
     void setGenerated(bool b)            { m_generated  = b;  }
     void setDefinition(Definition *d)    { m_definition = d;  }
     void setTitle(const QCString &t)     { m_title      = t;  }
+    void setLevel(int l)                 { m_level      = l;  }
+    void setReference(const QCString &r) { m_ref        = r;  }
+    void setLineNr(int l)                { m_lineNr     = l;  }
 
   private:
     QCString    m_label;
@@ -148,8 +151,21 @@ class SectionManager : public LinkedMap<SectionInfo>
     SectionInfo *replace(const QCString &label, const QCString &fileName, int lineNr,
                          const QCString &title, SectionType type, int level,const QCString &ref=QCString())
     {
-      LinkedMap<SectionInfo>::del(label.data());
-      return LinkedMap<SectionInfo>::add(label.data(),fileName,lineNr,title,type,level,ref);
+      SectionInfo *si = LinkedMap<SectionInfo>::find(label.data());
+      if (si)
+      {
+        si->setFileName(fileName);
+        si->setLineNr(lineNr);
+        si->setTitle(title);
+        si->setType(type);
+        si->setLevel(level);
+        si->setReference(ref);
+        return si;
+      }
+      else
+      {
+        return LinkedMap<SectionInfo>::add(label.data(),fileName,lineNr,title,type,level,ref);
+      }
     }
 
     //! returns a reference to the singleton
index a674c71..b82cf34 100644 (file)
 %option extra-type="struct sqlcodeYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -51,9 +55,10 @@ struct sqlcodeYY_state
      CodeOutputInterface * code;
      const char   *inputString;     //!< the code fragment as text
      yy_size_t     inputPosition;   //!< read offset during parsing
+     QCString      fileName;
      int           inputLines;      //!< number of line in the code fragment
      int           yyLineNr;        //!< current line number
-     bool          needsTermination;
+     bool          insideCodeLine;
      const Definition   *searchCtx;
 
      bool          exampleBlock;
@@ -84,6 +89,10 @@ static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
 #undef YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
+
 %}
 
 nl              (\r\n|\r|\n)
@@ -238,24 +247,28 @@ static void startCodeLine(yyscan_t yyscanner)
       {
         yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
                             yyextra->currentMemberDef->getOutputFileBase(),
-                            yyextra->currentMemberDef->anchor(),yyextra->yyLineNr);
+                            yyextra->currentMemberDef->anchor(),yyextra->yyLineNr,
+                            !yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
       else
       {
         yyextra->code->writeLineNumber(d->getReference(),
                             d->getOutputFileBase(),
-                            QCString(),yyextra->yyLineNr);
+                            QCString(),yyextra->yyLineNr,
+                            !yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
     }
     else
     {
-      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr);
+      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr,
+                                     !yyextra->includeCodeFragment);
     }
   }
 
   yyextra->code->startCodeLine(yyextra->sourceFileDef);
+  yyextra->insideCodeLine=true;
 
   if (yyextra->currentFontClass)
   {
@@ -278,13 +291,17 @@ static void endCodeLine(yyscan_t yyscanner)
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   endFontClass(yyscanner);
   yyextra->code->endCodeLine();
+  yyextra->insideCodeLine=false;
 }
 
 static void nextCodeLine(yyscan_t yyscanner)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   const char *fc = yyextra->currentFontClass;
-  endCodeLine(yyscanner);
+  if (yyextra->insideCodeLine)
+  {
+    endCodeLine(yyscanner);
+  }
   if (yyextra->yyLineNr<yyextra->inputLines)
   {
     yyextra->currentFontClass = fc;
@@ -344,8 +361,7 @@ static int countLines(yyscan_t yyscanner)
   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++,
-    yyextra->needsTermination=true;
+    count++;
   }
   return count;
 }
@@ -417,12 +433,13 @@ void SQLCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
   if (input.isEmpty()) return;
 
   printlex(yy_flex_debug, true, __FILE__, fileDef ? qPrint(fileDef->fileName()): NULL);
+  yyextra->fileName      = fileDef ? fileDef->fileName():"";
 
   yyextra->code = &codeOutIntf;
   yyextra->inputString   = input.data();
   yyextra->inputPosition = 0;
   yyextra->currentFontClass = 0;
-  yyextra->needsTermination = false;
+  yyextra->insideCodeLine = false;
   yyextra->searchCtx=searchCtx;
 
   if (startLine!=-1)
@@ -461,7 +478,7 @@ void SQLCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
 
   sqlcodeYYlex(yyscanner);
 
-  if (yyextra->needsTermination)
+  if (yyextra->insideCodeLine)
   {
     endCodeLine(yyscanner);
   }
index 68c93da..29b5d6a 100644 (file)
@@ -25,6 +25,7 @@
 #include "defargs.h"
 
 static std::mutex g_cacheMutex;
+static std::recursive_mutex g_cacheTypedefMutex;
 
 //--------------------------------------------------------------------------------------
 
@@ -494,6 +495,7 @@ const ClassDef *SymbolResolver::Private::newResolveTypedef(
                   QCString *pResolvedType,                             // out
                   const std::unique_ptr<ArgumentList> &actTemplParams) // in
 {
+  std::lock_guard<std::recursive_mutex> lock(g_cacheTypedefMutex);
   //printf("newResolveTypedef(md=%p,cachedVal=%p)\n",md,md->getCachedTypedefVal());
   bool isCached = md->isTypedefValCached(); // value already cached
   if (isCached)
@@ -1039,6 +1041,7 @@ const ClassDef *SymbolResolver::resolveClass(const Definition *scope,
       (scope->definitionType()!=Definition::TypeClass &&
        scope->definitionType()!=Definition::TypeNamespace
       ) ||
+      (name.stripWhiteSpace().startsWith("::")) ||
       (scope->getLanguage()==SrcLangExt_Java && QCString(name).find("::")!=-1)
      )
   {
@@ -1046,7 +1049,7 @@ const ClassDef *SymbolResolver::resolveClass(const Definition *scope,
   }
   //fprintf(stderr,"------------ resolveClass(scope=%s,name=%s,mayUnlinkable=%d)\n",
   //    scope?qPrint(scope->name()):"<global>",
-  //    name,
+  //    qPrint(name),
   //    mayBeUnlinkable
   //   );
   const ClassDef *result;
@@ -1068,12 +1071,12 @@ const ClassDef *SymbolResolver::resolveClass(const Definition *scope,
   {
     if (!mayBeHidden || !result->isHidden())
     {
-      //printf("result was %s\n",result?qPrint(result->name()):"<none>");
+      //fprintf(stderr,"result was %s\n",result?qPrint(result->name()):"<none>");
       result=0; // don't link to artificial/hidden classes unless explicitly allowed
     }
   }
   //fprintf(stderr,"ResolvedClass(%s,%s)=%s\n",scope?qPrint(scope->name()):"<global>",
-  //                                  name,result?qPrint(result->name()):"<none>");
+  //                                  qPrint(name),result?qPrint(result->name()):"<none>");
   return result;
 }
 
index 6dca1cd..5ff51ae 100644 (file)
 #include "containers.h"
 #include "debug.h"
 
+// set to 1 for debugging
+#define DUMP_OUTPUT 0
+
+// ----------------- private part -----------------------------------------------
+
+namespace {
+
 /** Information about an linkable anchor */
 class TagAnchorInfo
 {
@@ -105,7 +112,7 @@ class TagCompoundInfo
     QCString name;
     QCString filename;
     std::vector<TagAnchorInfo> docAnchors;
-    int lineNr;
+    int lineNr = 0;
   private:
     CompoundType m_type;
 };
@@ -985,6 +992,7 @@ void TagFileParser::startCompound( const XMLHandlers::Attributes& attrib )
   }
 }
 
+#if DUMP_OUTPUT
 /*! Dumps the internal structures. For debugging only! */
 void TagFileParser::dump()
 {
@@ -1156,6 +1164,7 @@ void TagFileParser::dump()
     }
   }
 }
+#endif
 
 void TagFileParser::addDocAnchors(const std::shared_ptr<Entry> &e,const std::vector<TagAnchorInfo> &l)
 {
@@ -1563,6 +1572,10 @@ void TagFileParser::addIncludes()
   }
 }
 
+} // namespace
+
+// ----------------- public part -----------------------------------------------
+
 void parseTagFile(const std::shared_ptr<Entry> &root,const char *fullName)
 {
   TagFileParser tagFileParser(fullName);
@@ -1579,5 +1592,7 @@ void parseTagFile(const std::shared_ptr<Entry> &root,const char *fullName)
   parser.parse(fullName,inputStr.data(),Debug::isFlagSet(Debug::Lex));
   tagFileParser.buildLists(root);
   tagFileParser.addIncludes();
-  //tagFileParser.dump();
+#if DUMP_OUTPUT
+  tagFileParser.dump();
+#endif
 }
index aeab71c..7b6954f 100755 (executable)
@@ -141,69 +141,194 @@ static QCString replace(const QCString &s,char csrc,char cdst)
 }
 #endif
 
-//- TemplateVariant implementation -------------------------------------------
+//- Template struct & list forward declarations ------------------------------
 
+class TemplateStruct;
+using TemplateStructPtr = std::shared_ptr<TemplateStruct>;
 
-TemplateVariant::TemplateVariant(TemplateStructIntf *s)
+/** @brief Default implementation of a context value of type struct. */
+class TemplateStruct : public TemplateStructIntf
 {
-  m_variant.set<TemplateStructIntf*>(s);
-  s->addRef();
-}
+  public:
+    // TemplateStructIntf methods
+    virtual TemplateVariant get(const QCString &name) const;
+    virtual StringVector fields() const;
 
-TemplateVariant::TemplateVariant(TemplateListIntf *l)
-{
-  m_variant.set<TemplateListIntf*>(l);
-  l->addRef();
-}
+    /** Creates an instance and returns a shared pointer to it */
+    static TemplateStructPtr alloc();
+
+    /** Sets the value the field of a struct
+     *  @param[in] name The name of the field.
+     *  @param[in] v The value to set.
+     */
+    virtual void set(const QCString &name,const TemplateVariant &v);
+
+    /** Removes the field from the struct */
+    virtual void remove(const QCString &name);
+
+    /** Creates a struct */
+    TemplateStruct() = default; //{ printf("%p:TemplateStruct::TemplateStruct()\n",(void*)this); }
+    /** Destroys the struct */
+    virtual ~TemplateStruct() = default; //{ printf("%p:TemplateStruct::~TemplateStruct()\n",(void*)this); }
+
+  private:
+
+    std::unordered_map<std::string,TemplateVariant> m_fields;
+};
 
-TemplateVariant::~TemplateVariant()
+void TemplateStruct::set(const QCString &name,const TemplateVariant &v)
 {
-  try
+  auto it = m_fields.find(name.str());
+  if (it!=m_fields.end()) // change existing field
   {
-    if      (m_variant.is<TemplateStructIntf*>()) m_variant.get<TemplateStructIntf*>()->release();
-    else if (m_variant.is<TemplateListIntf*>())   m_variant.get<TemplateListIntf*>()->release();
+    it->second = v;
   }
-  catch(...)
+  else // insert new field
   {
-    // should never happen
+    m_fields.insert(std::make_pair(name.str(),v));
   }
 }
 
-TemplateVariant::TemplateVariant(const TemplateVariant &v)
+void TemplateStruct::remove(const QCString &name)
 {
-  m_raw     = v.m_raw;
-  m_variant = v.m_variant;
-  if      (m_variant.is<TemplateStructIntf*>()) m_variant.get<TemplateStructIntf*>()->addRef();
-  else if (m_variant.is<TemplateListIntf*>())   m_variant.get<TemplateListIntf*>()->addRef();
+  auto it = m_fields.find(name.str());
+  if (it!=m_fields.end())
+  {
+    m_fields.erase(it);
+  }
 }
 
-TemplateVariant::TemplateVariant(TemplateVariant &&v)
+TemplateVariant TemplateStruct::get(const QCString &name) const
 {
-  m_raw     = std::move(v.m_raw);
-  m_variant = std::move(v.m_variant);
-  v.m_variant.invalidate();
+  auto it = m_fields.find(name.str());
+  return it!=m_fields.end() ? it->second : TemplateVariant();
 }
 
-TemplateVariant &TemplateVariant::operator=(const TemplateVariant &v)
+StringVector TemplateStruct::fields() const
 {
-  if (this!=&v)
+  StringVector result;
+  for (const auto &kv : m_fields)
   {
-    // assignment can change the type of the variable, so we have to be
-    // careful with reference counted content.
-    TemplateStructIntf *tmpStruct = m_variant.is<TemplateStructIntf*>() ? m_variant.get<TemplateStructIntf*>() : nullptr;
-    TemplateListIntf   *tmpList   = m_variant.is<TemplateListIntf*>()   ? m_variant.get<TemplateListIntf*>()   : nullptr;
+    result.push_back(kv.first);
+  }
+  std::sort(result.begin(),result.end());
+  return result;
+}
+
+TemplateStructPtr TemplateStruct::alloc()
+{
+  return std::make_shared<TemplateStruct>();
+}
 
-    m_raw      = v.m_raw;
-    m_variant  = v.m_variant;
+class TemplateList;
+using TemplateListPtr = std::shared_ptr<TemplateList>;
 
-    if      (m_variant.is<TemplateStructIntf*>()) m_variant.get<TemplateStructIntf*>()->addRef();
-    else if (m_variant.is<TemplateListIntf*>())   m_variant.get<TemplateListIntf*>()->addRef();
+//- Template list implementation ----------------------------------------------
 
-    // release overwritten reference counted values
-    if      (tmpStruct) tmpStruct->release();
-    else if (tmpList  ) tmpList->release();
-  }
-  return *this;
+// iterator support
+template<class List>
+class TemplateListGenericConstIterator : public TemplateListIntf::ConstIterator
+{
+  public:
+    TemplateListGenericConstIterator(const List &l) : m_list(l) { m_index=0; }
+    virtual ~TemplateListGenericConstIterator() {}
+    virtual void toFirst()
+    {
+      m_index=0;
+    }
+    virtual void toLast()
+    {
+      uint count = m_list.count();
+      m_index = count>0 ? count-1 : 0;
+    }
+    virtual void toNext()
+    {
+      if (m_index<m_list.count()) { m_index++; }
+    }
+    virtual void toPrev()
+    {
+      if (m_index>0) { --m_index; }
+    }
+    virtual bool current(TemplateVariant &v) const
+    {
+      if (m_index<m_list.count())
+      {
+        v = m_list.at(m_index);
+        return TRUE;
+      }
+      else
+      {
+        v = TemplateVariant();
+        return FALSE;
+      }
+    }
+  private:
+    const List &m_list;
+    size_t m_index = 0;
+};
+
+//-------------------------------------------------------------------------------
+//
+/** @brief Default implementation of a context value of type list. */
+class TemplateList : public TemplateListIntf
+{
+  public:
+    // TemplateListIntf methods
+    virtual uint count() const
+    {
+      return static_cast<uint>(m_elems.size());
+    }
+    virtual TemplateVariant at(uint index) const
+    {
+      return index < m_elems.size() ?  m_elems[index] : TemplateVariant();
+    }
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const
+    {
+      return std::make_unique< TemplateListGenericConstIterator<TemplateList> >(*this);
+    }
+
+    /** Creates an instance and returns a shared pointer to it */
+    static TemplateListPtr alloc()
+    {
+      return std::make_shared<TemplateList>();
+    }
+
+    /** Appends element \a v to the end of the list */
+    virtual void append(const TemplateVariant &v)
+    {
+      m_elems.push_back(v);
+    }
+
+    void removeAt(uint index)
+    {
+      if (index<m_elems.size())
+      {
+        m_elems.erase(m_elems.begin()+index);
+      }
+    }
+
+    void insertAt(uint index,TemplateListPtr list)
+    {
+      auto it = m_elems.begin()+index;
+      m_elems.insert(it,list->m_elems.begin(),list->m_elems.end());
+    }
+
+    /** Creates a list */
+    TemplateList() = default; //{ printf("%p:TemplateList::TemplateList()\n",(void*)this); }
+    /** Destroys the list */
+    virtual ~TemplateList() = default; //{ printf("%p:TemplateList::~TemplateList()\n",(void*)this); }
+
+  private:
+    TemplateVariantList m_elems;
+};
+
+//- TemplateVariant implementation -------------------------------------------
+
+TemplateVariant::TemplateVariant(TemplateVariant &&v)
+{
+  m_raw     = std::move(v.m_raw);
+  m_variant = std::move(v.m_variant);
+  v.m_variant.invalidate();
 }
 
 TemplateVariant &TemplateVariant::operator=(TemplateVariant &&v)
@@ -214,17 +339,43 @@ TemplateVariant &TemplateVariant::operator=(TemplateVariant &&v)
   return *this;
 }
 
+bool TemplateVariant::operator==(TemplateVariant &other) const
+{
+  if (!m_variant.valid())
+  {
+    return FALSE;
+  }
+  if (isBool() && other.isBool())
+  {
+    return m_variant.get<static_cast<uint8_t>(Type::Bool)>() == other.m_variant.get<static_cast<uint8_t>(Type::Bool)>();
+  }
+  else if (isInt() && other.isInt())
+  {
+    return m_variant.get<static_cast<uint8_t>(Type::Int)>() == other.m_variant.get<static_cast<uint8_t>(Type::Int)>();
+  }
+  else if (isList() && other.isList())
+  {
+    return toList() == other.toList();
+  }
+  else if ((isStruct() || isWeakStruct()) && (other.isStruct() || other.isWeakStruct()))
+  {
+    return toStruct() == other.toStruct();
+  }
+  return toString()==other.toString();
+}
+
 bool TemplateVariant::toBool() const
 {
   switch (type())
   {
-    case Type::None:     return false;
-    case Type::Bool:     return m_variant.get<bool>();
-    case Type::Int:      return m_variant.get<int>()!=0;
-    case Type::String:   return !m_variant.get<QCString>().isEmpty();
-    case Type::Struct:   return true;
-    case Type::List:     return m_variant.get<TemplateListIntf*>()->count()!=0;
-    case Type::Function: return false;
+    case Type::None:       return false;
+    case Type::Bool:       return m_variant.get<static_cast<uint8_t>(Type::Bool)>();
+    case Type::Int:        return m_variant.get<static_cast<uint8_t>(Type::Int)>()!=0;
+    case Type::String:     return !m_variant.get<static_cast<uint8_t>(Type::String)>().isEmpty();
+    case Type::Struct:     return true;
+    case Type::List:       return m_variant.get<static_cast<uint8_t>(Type::List)>()->count()!=0;
+    case Type::Function:   return false;
+    case Type::WeakStruct: return true;
   }
   return FALSE;
 }
@@ -233,13 +384,14 @@ int TemplateVariant::toInt() const
 {
   switch (type())
   {
-    case Type::None:     return 0;
-    case Type::Bool:     return m_variant.get<bool>() ? 1 : 0;
-    case Type::Int:      return m_variant.get<int>();
-    case Type::String:   return !m_variant.get<QCString>().toInt();
-    case Type::Struct:   return 0;
-    case Type::List:     return m_variant.get<TemplateListIntf*>()->count();
-    case Type::Function: return 0;
+    case Type::None:       return 0;
+    case Type::Bool:       return m_variant.get<static_cast<uint8_t>(Type::Bool)>() ? 1 : 0;
+    case Type::Int:        return m_variant.get<static_cast<uint8_t>(Type::Int)>();
+    case Type::String:     return !m_variant.get<static_cast<uint8_t>(Type::String)>().toInt();
+    case Type::Struct:     return 0;
+    case Type::List:       return m_variant.get<static_cast<uint8_t>(Type::List)>()->count();
+    case Type::Function:   return 0;
+    case Type::WeakStruct: return 0;
   }
   return 0;
 }
@@ -248,75 +400,90 @@ QCString TemplateVariant::toString() const
 {
   switch (type())
   {
-    case Type::None:     return QCString();
-    case Type::Bool:     return m_variant.get<bool>() ? "true" : "false";
-    case Type::Int:      return QCString().setNum(m_variant.get<int>());
-    case Type::String:   return m_variant.get<QCString>();
-    case Type::Struct:   return structToString();
-    case Type::List:     return listToString();
-    case Type::Function: return "[function]";
+    case Type::None:       return QCString();
+    case Type::Bool:       return m_variant.get<static_cast<uint8_t>(Type::Bool)>() ? "true" : "false";
+    case Type::Int:        return QCString().setNum(m_variant.get<static_cast<uint8_t>(Type::Int)>());
+    case Type::String:     return m_variant.get<static_cast<uint8_t>(Type::String)>();
+    case Type::Struct:     return structToString();
+    case Type::List:       return listToString();
+    case Type::Function:   return "[function]";
+    case Type::WeakStruct: return structToString();
   }
   return QCString();
 }
 
-
-//- Template struct implementation --------------------------------------------
-
-
-/** @brief Private data of a template struct object */
-class TemplateStruct::Private
+/** Return a string representation of the type of the value stored in the variant */
+const char *TemplateVariant::typeAsString() const
 {
-  public:
-    Private() : refCount(0) {}
-    std::unordered_map<std::string,TemplateVariant> fields;
-    int refCount = 0;
-};
+  switch (type())
+  {
+    case Type::None:       return "invalid";
+    case Type::Bool:       return "bool";
+    case Type::Int:        return "integer";
+    case Type::String:     return "string";
+    case Type::Struct:     return "struct";
+    case Type::List:       return "list";
+    case Type::Function:   return "function";
+    case Type::WeakStruct: return "struct";
+  }
+  return "invalid";
+}
 
-TemplateStruct::TemplateStruct()
+TemplateListIntfPtr TemplateVariant::toList()
+{
+  return isList() ? m_variant.get<static_cast<uint8_t>(Type::List)>() : nullptr;
+}
+const TemplateListIntfPtr TemplateVariant::toList() const
 {
-  p = new Private;
+  return isList() ? m_variant.get<static_cast<uint8_t>(Type::List)>() : nullptr;
 }
 
-TemplateStruct::~TemplateStruct()
+TemplateStructIntfPtr TemplateVariant::toStruct()
 {
-  delete p;
+  return isStruct()     ? m_variant.get<static_cast<uint8_t>(Type::Struct)>() :
+         isWeakStruct() ? m_variant.get<static_cast<uint8_t>(Type::WeakStruct)>().lock() :
+         nullptr;
+}
+const TemplateStructIntfPtr TemplateVariant::toStruct() const
+{
+  return isStruct()     ? m_variant.get<static_cast<uint8_t>(Type::Struct)>() :
+         isWeakStruct() ? m_variant.get<static_cast<uint8_t>(Type::WeakStruct)>().lock() :
+         nullptr;
 }
 
-int TemplateStruct::addRef()
+TemplateVariant TemplateVariant::call(const std::vector<TemplateVariant> &args)
 {
-  return ++p->refCount;
+  return isFunction() ? m_variant.get<static_cast<uint8_t>(Type::Function)>()(args) : TemplateVariant();
 }
 
-int TemplateStruct::release()
+//- Template struct implementation --------------------------------------------
+
+
+/** @brief Private data of a template struct object */
+class TemplateImmutableStruct::Private
+{
+  public:
+    Private(std::initializer_list<StructField> fs) : fields(fs) {}
+    std::unordered_map<std::string,TemplateVariant> fields;
+};
+
+TemplateImmutableStruct::TemplateImmutableStruct(
+    std::initializer_list<StructField> fields)
+  : p(std::make_unique<Private>(fields))
 {
-  int count = --p->refCount;
-  if (count<=0)
-  {
-    delete this;
-  }
-  return count;
 }
 
-void TemplateStruct::set(const QCString &name,const TemplateVariant &v)
+TemplateImmutableStruct::~TemplateImmutableStruct()
 {
-  auto it = p->fields.find(name.str());
-  if (it!=p->fields.end()) // change existing field
-  {
-    it->second = v;
-  }
-  else // insert new field
-  {
-    p->fields.insert(std::make_pair(name.str(),v));
-  }
 }
 
-TemplateVariant TemplateStruct::get(const QCString &name) const
+TemplateVariant TemplateImmutableStruct::get(const QCString &name) const
 {
   auto it = p->fields.find(name.str());
   return it!=p->fields.end() ? it->second : TemplateVariant();
 }
 
-StringVector TemplateStruct::fields() const
+StringVector TemplateImmutableStruct::fields() const
 {
   StringVector result;
   for (const auto &kv : p->fields)
@@ -327,133 +494,60 @@ StringVector TemplateStruct::fields() const
   return result;
 }
 
-TemplateStruct *TemplateStruct::alloc()
+TemplateStructIntfPtr TemplateImmutableStruct::alloc(std::initializer_list<StructField> fields)
 {
-  return new TemplateStruct;
+  return std::make_shared<TemplateImmutableStruct>(fields);
 }
 
-//- Template list implementation ----------------------------------------------
-
+//- Template immutable list implementation ------------------------------------
 
-/** @brief Private data of a template list object */
-class TemplateList::Private
+/** @brief Private data of a template immutable list object */
+class TemplateImmutableList::Private
 {
   public:
-    Private() : index(-1), refCount(0) {}
-    std::vector<TemplateVariant> elems;
+    Private(std::initializer_list<TemplateVariant> e) : elems(e) {}
+    Private(const TemplateVariantList &e) : elems(e) {}
+    TemplateVariantList elems;
     int index = -1;
-    int refCount = 0;
 };
 
-
-TemplateList::TemplateList()
+TemplateImmutableList::TemplateImmutableList(std::initializer_list<TemplateVariant> elements)
+  : p(std::make_unique<Private>(elements))
 {
-  p = new Private;
 }
 
-TemplateList::~TemplateList()
+TemplateImmutableList::TemplateImmutableList(const TemplateVariantList &elements)
+  : p(std::make_unique<Private>(elements))
 {
-  delete p;
 }
 
-int TemplateList::addRef()
+TemplateImmutableList::~TemplateImmutableList()
 {
-  return ++p->refCount;
 }
 
-int TemplateList::release()
-{
-  int count = --p->refCount;
-  if (count<=0)
-  {
-    delete this;
-  }
-  return count;
-}
-
-uint TemplateList::count() const
+uint TemplateImmutableList::count() const
 {
   return static_cast<uint>(p->elems.size());
 }
 
-void TemplateList::append(const TemplateVariant &v)
-{
-  p->elems.push_back(v);
-}
-
-// iterator support
-class TemplateListConstIterator : public TemplateListIntf::ConstIterator
-{
-  public:
-    TemplateListConstIterator(const TemplateList &l) : m_list(l) { m_index=0; }
-    virtual ~TemplateListConstIterator() {}
-    virtual void toFirst()
-    {
-      m_index=0;
-    }
-    virtual void toLast()
-    {
-      if (m_list.p->elems.size()>0)
+TemplateListIntf::ConstIteratorPtr TemplateImmutableList::createIterator() const
       {
-        m_index=m_list.p->elems.size()-1;
+  return std::make_unique< TemplateListGenericConstIterator<TemplateImmutableList> >(*this);
       }
-      else
-      {
-        m_index=0;
-      }
-    }
-    virtual void toNext()
-    {
-      if (m_index<m_list.p->elems.size())
-      {
-        m_index++;
-      }
-    }
-    virtual void toPrev()
-    {
-      if (m_index>0)
-      {
-        --m_index;
-      }
-    }
-    virtual bool current(TemplateVariant &v) const
-    {
-      if (m_index<m_list.p->elems.size())
-      {
-        v = m_list.p->elems[m_index];
-        return TRUE;
-      }
-      else
-      {
-        v = TemplateVariant();
-        return FALSE;
-      }
-    }
-  private:
-    const TemplateList &m_list;
-    size_t m_index = 0;
-};
 
-TemplateListIntf::ConstIterator *TemplateList::createIterator() const
+TemplateVariant TemplateImmutableList::at(uint index) const
 {
-  return new TemplateListConstIterator(*this);
+  return index<p->elems.size() ? p->elems[index] : TemplateVariant();
 }
 
-TemplateVariant TemplateList::at(uint index) const
+TemplateListIntfPtr TemplateImmutableList::alloc(std::initializer_list<TemplateVariant> elements)
 {
-  if (index<p->elems.size())
-  {
-    return p->elems[index];
-  }
-  else
-  {
-    return TemplateVariant();
-  }
+  return std::make_shared<TemplateImmutableList>(elements);
 }
 
-TemplateList *TemplateList::alloc()
+TemplateListIntfPtr TemplateImmutableList::alloc(const TemplateVariantList &elements)
 {
-  return new TemplateList;
+  return std::make_shared<TemplateImmutableList>(elements);
 }
 
 //- Operator types ------------------------------------------------------------
@@ -549,27 +643,38 @@ class TemplateContextImpl : public TemplateContext
     TemplateContextImpl(const TemplateEngine *e);
     virtual ~TemplateContextImpl();
 
+    using EscapeIntfMap = std::unordered_map<std::string, std::unique_ptr<TemplateEscapeIntf>>;
+    void copyEscapeIntfMap(const EscapeIntfMap &map)
+    {
+      for (const auto &kv : map)
+      {
+        m_escapeIntfMap.insert(std::make_pair(kv.first,kv.second->clone()));
+      }
+    }
+
     // TemplateContext methods
     void push();
     void pop();
     void set(const QCString &name,const TemplateVariant &v);
-    void update(const QCString &name,const TemplateVariant &v);
+    //void update(const QCString &name,const TemplateVariant &v);
     TemplateVariant get(const QCString &name) const;
     const TemplateVariant *getRef(const QCString &name) const;
     void setOutputDirectory(const QCString &dir)
     { m_outputDir = dir; }
-    void setEscapeIntf(const QCString &ext,TemplateEscapeIntf *intf)
+    void setEscapeIntf(const QCString &ext,std::unique_ptr<TemplateEscapeIntf> intf)
     {
       int i=(!ext.isEmpty() && ext.at(0)=='.') ? 1 : 0;
-      m_escapeIntfMap.insert(std::make_pair(ext.mid(i).str(),intf));
+      m_escapeIntfMap.insert(std::make_pair(ext.mid(i).str(),std::move(intf)));
     }
     void selectEscapeIntf(const QCString &ext)
     {
       auto it = m_escapeIntfMap.find(ext.str());
-      m_activeEscapeIntf = it!=m_escapeIntfMap.end() ? it->second : 0;
+      m_activeEscapeIntf = it!=m_escapeIntfMap.end() ? it->second.get() : 0;
     }
     void setActiveEscapeIntf(TemplateEscapeIntf *intf) { m_activeEscapeIntf = intf; }
-    void setSpacelessIntf(TemplateSpacelessIntf *intf) { m_spacelessIntf = intf; }
+    TemplateEscapeIntf *escapeIntf() { return m_activeEscapeIntf; }
+    const TemplateEscapeIntf *escapeIntf() const { return m_activeEscapeIntf; }
+    void setSpacelessIntf(std::unique_ptr<TemplateSpacelessIntf> intf) { m_spacelessIntf = std::move(intf); }
 
     // internal methods
     TemplateBlockContext *blockContext();
@@ -579,8 +684,8 @@ class TemplateContextImpl : public TemplateContext
     QCString templateName() const                { return m_templateName; }
     int line() const                             { return m_line; }
     QCString outputDirectory() const             { return m_outputDir; }
-    TemplateEscapeIntf *escapeIntf() const       { return m_activeEscapeIntf; }
-    TemplateSpacelessIntf *spacelessIntf() const { return m_spacelessIntf; }
+    std::unique_ptr<TemplateSpacelessIntf> &spacelessIntf() { return m_spacelessIntf; }
+    const std::unique_ptr<TemplateSpacelessIntf> &spacelessInfo() const { return m_spacelessIntf; }
     void enableSpaceless(bool b)                 { if (b && !m_spacelessEnabled) m_spacelessIntf->reset();
                                                    m_spacelessEnabled=b;
                                                  }
@@ -599,20 +704,21 @@ class TemplateContextImpl : public TemplateContext
     void openSubIndex(const QCString &indexName);
     void closeSubIndex(const QCString &indexName);
     void addIndexEntry(const QCString &indexName,const std::vector<TemplateKeyValue> &arguments);
+    const TemplateStructPtr indices() const { return m_indices; }
 
   private:
     const TemplateEngine *m_engine = 0;
-    QCString m_templateName;
-    int m_line = 0;
+    QCString m_templateName = "<unknown>";
+    int m_line = 1;
     QCString m_outputDir;
-    std::deque< std::map<std::string,TemplateVariant> > m_contextStack;
+    std::deque< std::unordered_map<std::string,TemplateVariant> > m_contextStack;
     TemplateBlockContext m_blockContext;
-    std::unordered_map<std::string, TemplateEscapeIntf*> m_escapeIntfMap;
+    EscapeIntfMap m_escapeIntfMap;
     TemplateEscapeIntf *m_activeEscapeIntf = 0;
-    TemplateSpacelessIntf *m_spacelessIntf = 0;
+    std::unique_ptr<TemplateSpacelessIntf> m_spacelessIntf;
     bool m_spacelessEnabled = false;
     bool m_tabbingEnabled = false;
-    TemplateAutoRef<TemplateStruct> m_indices;
+    TemplateStructPtr m_indices;
     std::unordered_map< std::string, std::stack<TemplateVariant> > m_indexStacks;
     QCString m_encoding;
     void *m_fromUtf8 = 0;
@@ -665,16 +771,24 @@ class FilterGet
   public:
     static TemplateVariant apply(const TemplateVariant &v,const TemplateVariant &arg)
     {
-      if (v.isValid() && v.isStruct() && arg.isString())
+      if (v.isValid() && (v.isStruct() || v.isWeakStruct()) && arg.isString())
       {
-        TemplateVariant result = v.toStruct()->get(arg.toString());
-        //printf("\nok[%s]=%d\n",qPrint(arg.toString()),result.type());
-        return result;
+        TemplateStructIntfPtr s = v.toStruct();
+        if (s)
+        {
+          TemplateVariant result = v.toStruct()->get(arg.toString());
+          //printf("\nok[%s]=%d\n",qPrint(arg.toString()),result.type());
+          return result;
+        }
+        else
+        {
+          return false;
+        }
       }
       else
       {
         //printf("\nnok[%s]\n",qPrint(arg.toString()));
-        return FALSE;
+        return false;
       }
     }
 };
@@ -706,33 +820,37 @@ class FilterKeep
   public:
     static TemplateVariant apply(const TemplateVariant &v,const TemplateVariant &args)
     {
-      if (v.isValid() && v.isList() && args.isString())
+      if (v.isValid() && (v.isList()) && args.isString())
       {
-        //printf("FilterKeep::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString()));
-        TemplateListIntf::ConstIterator *it = v.toList()->createIterator();
-
-        TemplateList *result = TemplateList::alloc();
-        TemplateVariant item;
-        for (it->toFirst();(it->current(item));it->toNext())
+        TemplateListIntfPtr list = v.toList();
+        if (list)
         {
-          //printf("item type=%s\n",item.typeAsString());
-          TemplateStructIntf *s = item.toStruct();
-          if (s)
+          //printf("FilterKeep::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString()));
+          TemplateListIntf::ConstIteratorPtr it = list->createIterator();
+
+          TemplateListPtr result = TemplateList::alloc();
+          TemplateVariant item;
+          for (it->toFirst();(it->current(item));it->toNext())
           {
-            TemplateVariant value = s->get(args.toString());
-            //printf("value type=%s\n",value.typeAsString());
-            if (value.toBool())
-            {
-              //printf("keeping it\n");
-              result->append(item);
-            }
-            else
+            //printf("item type=%s\n",item.typeAsString());
+            TemplateStructIntfPtr s = item.toStruct();
+            if (s)
             {
-              //printf("Dropping it\n");
+              TemplateVariant value = s->get(args.toString());
+              //printf("value type=%s\n",value.typeAsString());
+              if (value.toBool())
+              {
+                //printf("keeping it\n");
+                result->append(item);
+              }
+              else
+              {
+                //printf("Dropping it\n");
+              }
             }
           }
+          return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(result));
         }
-        return result;
       }
       return v;
     }
@@ -753,9 +871,9 @@ class FilterList
           return v;
         }
         // create a list with v as the only element
-        TemplateList *list = TemplateList::alloc();
+        TemplateListPtr list = TemplateList::alloc();
         list->append(v);
-        return list;
+        return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(list));
       }
       else
       {
@@ -905,36 +1023,39 @@ class FilterFlatten
       }
       else
       {
-        TemplateList *list = TemplateList::alloc();
-        flatten(v.toList(),list);
-        return TemplateVariant(list);
+        TemplateListPtr list = TemplateList::alloc();
+        TemplateListIntfPtr tree = v.toList();
+        flatten(tree,list);
+        return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(list));
       }
     }
 
   private:
-    static void flatten(const TemplateListIntf *tree,TemplateList *list)
+    static void flatten(const TemplateListIntfPtr tree,TemplateListPtr list)
     {
-      TemplateListIntf::ConstIterator *it = tree->createIterator();
-      TemplateVariant item;
-      for (it->toFirst();(it->current(item));it->toNext())
+      if (tree)
       {
-        TemplateStructIntf *s = item.toStruct();
-        if (s)
+        TemplateListIntf::ConstIteratorPtr it = tree->createIterator();
+        TemplateVariant item;
+        for (it->toFirst();(it->current(item));it->toNext())
         {
-          list->append(item);
-          // if s has "children" then recurse into the children
-          TemplateVariant children = s->get("children");
-          if (children.isValid() && children.isList())
+          TemplateStructIntfPtr s = item.toStruct();
+          if (s)
           {
-            flatten(children.toList(),list);
+            list->append(item);
+            // if s has "children" then recurse into the children
+            TemplateVariant children = s->get("children");
+            if (children.isValid() && children.isList())
+            {
+              flatten(children.toList(),list);
+            }
+          }
+          else
+          {
+            list->append(item);
           }
-        }
-        else
-        {
-          list->append(item);
         }
       }
-      delete it;
     }
 };
 
@@ -955,44 +1076,47 @@ class FilterListSort
       if (v.isList() && args.isString())
       {
         //printf("FilterListSort::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString()));
-        TemplateListIntf::ConstIterator *it = v.toList()->createIterator();
+        TemplateListIntfPtr list = v.toList();
+        if (list)
+        {
+          TemplateListIntf::ConstIteratorPtr it = list->createIterator();
 
-        TemplateVariant item;
-        TemplateList *result = TemplateList::alloc();
+          TemplateVariant item;
+          TemplateListPtr result = TemplateList::alloc();
 
-        // create list of items based on v using the data in args as a sort key
-        using SortList = std::vector<ListElem>;
-        SortList sortList;
-        sortList.reserve(v.toList()->count());
-        for (it->toFirst();(it->current(item));it->toNext())
-        {
-          TemplateStructIntf *s = item.toStruct();
-          if (s)
+          // create list of items based on v using the data in args as a sort key
+          using SortList = std::vector<ListElem>;
+          SortList sortList;
+          sortList.reserve(v.toList()->count());
+          for (it->toFirst();(it->current(item));it->toNext())
           {
-            QCString sortKey = determineSortKey(s,args.toString());
-            sortList.emplace_back(sortKey,item);
-            //printf("sortKey=%s\n",qPrint(sortKey));
+            TemplateStructIntfPtr s = item.toStruct();
+            if (s)
+            {
+              QCString sortKey = determineSortKey(s,args.toString());
+              sortList.emplace_back(sortKey,item);
+              //printf("sortKey=%s\n",qPrint(sortKey));
+            }
           }
-        }
-        delete it;
 
-        // sort the list
-        std::sort(sortList.begin(),
-                  sortList.end(),
-                  [](const auto &lhs,const auto &rhs) { return lhs.key < rhs.key; });
+          // sort the list
+          std::sort(sortList.begin(),
+              sortList.end(),
+              [](const auto &lhs,const auto &rhs) { return lhs.key < rhs.key; });
 
-        // add sorted items to the result list
-        for (const auto &elem : sortList)
-        {
-          result->append(elem.value);
+          // add sorted items to the result list
+          for (const auto &elem : sortList)
+          {
+            result->append(elem.value);
+          }
+          return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(result));
         }
-        return result;
       }
       return v;
     }
 
   private:
-    static QCString determineSortKey(TemplateStructIntf *s,const QCString &arg)
+    static QCString determineSortKey(const TemplateStructIntfPtr s,const QCString &arg)
     {
       int i,p=0;
       QCString result;
@@ -1034,53 +1158,56 @@ class FilterGroupBy
     {
       if (v.isList() && args.isString())
       {
-        //printf("FilterListSort::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString()));
-        TemplateListIntf::ConstIterator *it = v.toList()->createIterator();
+        TemplateListIntfPtr list = v.toList();
+        if (list)
+        {
+          //printf("FilterListSort::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString()));
+          TemplateListIntf::ConstIteratorPtr it = list->createIterator();
 
-        TemplateVariant item;
-        TemplateList *result = TemplateList::alloc();
+          TemplateVariant item;
+          TemplateListPtr result = TemplateList::alloc();
 
-        // create list of items based on v using the data in args as a sort key
-        using SortList = std::vector<ListElem>;
-        SortList sortList;
-        sortList.reserve(v.toList()->count());
-        for (it->toFirst();(it->current(item));it->toNext())
-        {
-          TemplateStructIntf *s = item.toStruct();
-          if (s)
+          // create list of items based on v using the data in args as a sort key
+          using SortList = std::vector<ListElem>;
+          SortList sortList;
+          sortList.reserve(v.toList()->count());
+          for (it->toFirst();(it->current(item));it->toNext())
           {
-            QCString sortKey = determineSortKey(s,args.toString());
-            sortList.emplace_back(sortKey,item);
-            //printf("sortKey=%s\n",qPrint(sortKey));
+            TemplateStructIntfPtr s = item.toStruct();
+            if (s)
+            {
+              QCString sortKey = determineSortKey(s,args.toString());
+              sortList.emplace_back(sortKey,item);
+              //printf("sortKey=%s\n",qPrint(sortKey));
+            }
           }
-        }
-        delete it;
 
-        // sort the list
-        std::sort(sortList.begin(),
-                  sortList.end(),
-                  [](const auto &lhs,const auto &rhs) { return lhs.key < rhs.key; });
+          // sort the list
+          std::sort(sortList.begin(),
+              sortList.end(),
+              [](const auto &lhs,const auto &rhs) { return lhs.key < rhs.key; });
 
-        // add sorted items to the result list
-        TemplateList *groupList=0;
-        QCString prevKey;
-        for (const auto &elem : sortList)
-        {
-          if (groupList==0 || elem.key!=prevKey)
+          // add sorted items to the result list
+          TemplateListPtr groupList;
+          QCString prevKey;
+          for (const auto &elem : sortList)
           {
-            groupList = TemplateList::alloc();
-            result->append(groupList);
-            prevKey = elem.key;
+            if (groupList==0 || elem.key!=prevKey)
+            {
+              groupList = TemplateList::alloc();
+              result->append(std::static_pointer_cast<TemplateListIntf>(groupList));
+              prevKey = elem.key;
+            }
+            groupList->append(elem.value);
           }
-          groupList->append(elem.value);
+          return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(result));
         }
-        return result;
       }
       return v;
     }
 
   private:
-    static QCString determineSortKey(TemplateStructIntf *s,const QCString &attribName)
+    static QCString determineSortKey(const TemplateStructIntfPtr s,const QCString &attribName)
     {
        TemplateVariant v = s->get(attribName);
        return v.toString();
@@ -1118,18 +1245,18 @@ class FilterPaginate
           args.isValid() && args.isInt())
       {
         int pageSize = args.toInt();
-        const TemplateListIntf *list   = v.toList();
-        TemplateList     *result = TemplateList::alloc();
-        TemplateListIntf::ConstIterator *it = list->createIterator();
+        const TemplateListIntfPtr list   = v.toList();
+        TemplateListPtr   result = TemplateList::alloc();
+        TemplateListIntf::ConstIteratorPtr it = list->createIterator();
         TemplateVariant   item;
-        TemplateList     *pageList=0;
+        TemplateListPtr   pageList;
         int i = 0;
         for (it->toFirst();(it->current(item));it->toNext())
         {
           if (pageList==0)
           {
             pageList = TemplateList::alloc();
-            result->append(pageList);
+            result->append(std::static_pointer_cast<TemplateListIntf>(pageList));
           }
           pageList->append(item);
           i++;
@@ -1139,8 +1266,7 @@ class FilterPaginate
             i=0;
           }
         }
-        delete it;
-        return result;
+        return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(result));
       }
       else // wrong arguments
       {
@@ -1184,7 +1310,7 @@ class FilterAlphaIndex
       //printf("<keyToLabel(%s)\n",qPrint(result));
       return result;
     }
-    static std::string determineSortKey(TemplateStructIntf *s,const QCString &attribName)
+    static std::string determineSortKey(const TemplateStructIntfPtr s,const QCString &attribName)
     {
        TemplateVariant v = s->get(attribName);
        int index = getPrefixIndex(v.toString());
@@ -1196,53 +1322,56 @@ class FilterAlphaIndex
     {
       if (v.isList() && args.isString())
       {
-        //printf("FilterListSort::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString()));
-        TemplateListIntf::ConstIterator *it = v.toList()->createIterator();
+        TemplateListIntfPtr list = v.toList();
+        if (list)
+        {
+          //printf("FilterListSort::apply: v=%s args=%s\n",qPrint(v.toString()),qPrint(args.toString()));
+          TemplateListIntf::ConstIteratorPtr it = list->createIterator();
 
-        TemplateVariant item;
-        TemplateList *result = TemplateList::alloc();
+          TemplateVariant item;
+          TemplateListPtr result = TemplateList::alloc();
 
-        // create list of items based on v using the data in args as a sort key
-        using SortList = std::vector<ListElem>;
-        SortList sortList;
-        sortList.reserve(v.toList()->count());
-        for (it->toFirst();(it->current(item));it->toNext())
-        {
-          TemplateStructIntf *s = item.toStruct();
-          if (s)
+          // create list of items based on v using the data in args as a sort key
+          using SortList = std::vector<ListElem>;
+          SortList sortList;
+          sortList.reserve(v.toList()->count());
+          for (it->toFirst();(it->current(item));it->toNext())
           {
-            std::string sortKey = determineSortKey(s,args.toString());
-            sortList.emplace_back(sortKey,item);
-            //printf("sortKey=%s\n",qPrint(sortKey));
+            TemplateStructIntfPtr s = item.toStruct();
+            if (s)
+            {
+              std::string sortKey = determineSortKey(s,args.toString());
+              sortList.emplace_back(sortKey,item);
+              //printf("sortKey=%s\n",qPrint(sortKey));
+            }
           }
-        }
-        delete it;
-
-        // sort the list
-        std::sort(sortList.begin(),
-                  sortList.end(),
-                  [](const auto &lhs,const auto &rhs) { return lhs.key < rhs.key; });
-
-        // create an index from the sorted list
-        std::string letter;
-        TemplateStruct *indexNode = 0;
-        TemplateList *indexList = 0;
-        for (const auto &elem : sortList)
-        {
-          if (letter!=elem.key || indexNode==0)
+
+          // sort the list
+          std::sort(sortList.begin(),
+              sortList.end(),
+              [](const auto &lhs,const auto &rhs) { return lhs.key < rhs.key; });
+
+          // create an index from the sorted list
+          std::string letter;
+          TemplateStructPtr indexNode;
+          TemplateListPtr indexList;
+          for (const auto &elem : sortList)
           {
-            // create new indexNode
-            indexNode = TemplateStruct::alloc();
-            indexList = TemplateList::alloc();
-            indexNode->set("letter", elem.key);
-            indexNode->set("label",  keyToLabel(elem.key.c_str()));
-            indexNode->set("items",indexList);
-            result->append(indexNode);
-            letter=elem.key;
+            if (letter!=elem.key || indexNode==0)
+            {
+              // create new indexNode
+              indexNode = TemplateStruct::alloc();
+              indexList = TemplateList::alloc();
+              indexNode->set("letter", elem.key);
+              indexNode->set("label",  keyToLabel(elem.key.c_str()));
+              indexNode->set("items",std::static_pointer_cast<TemplateListIntf>(indexList));
+              result->append(std::static_pointer_cast<TemplateStructIntf>(indexNode));
+              letter=elem.key;
+            }
+            indexList->append(elem.value);
           }
-          indexList->append(elem.value);
+          return TemplateVariant(std::static_pointer_cast<TemplateListIntf>(result));
         }
-        return result;
       }
       return v;
     }
@@ -1456,11 +1585,11 @@ class TemplateFilterFactory
   public:
     typedef TemplateVariant (FilterFunction)(const TemplateVariant &v,const TemplateVariant &arg);
 
-    static TemplateFilterFactory *instance()
+    static TemplateFilterFactory &instance()
     {
-      static TemplateFilterFactory *instance = 0;
-      if (instance==0) instance = new TemplateFilterFactory;
-      return instance;
+      static std::unique_ptr<TemplateFilterFactory> instance;
+      if (instance==0) instance = std::make_unique<TemplateFilterFactory>();
+      return *instance;
     }
 
     TemplateVariant apply(const QCString &name,const TemplateVariant &v,const TemplateVariant &arg, bool &ok)
@@ -1489,7 +1618,7 @@ class TemplateFilterFactory
       public:
         AutoRegister<T>(const QCString &key)
         {
-          TemplateFilterFactory::instance()->registerFilter(key,&T::apply);
+          TemplateFilterFactory::instance().registerFilter(key,&T::apply);
         }
     };
 
@@ -1538,7 +1667,8 @@ class ExprAst
     virtual TemplateVariant resolve(TemplateContext *) { return TemplateVariant(); }
 };
 
-using ExprAstList = std::vector< std::unique_ptr<ExprAst> >;
+using ExprAstPtr = std::unique_ptr<ExprAst>;
+using ExprAstList = std::vector< ExprAstPtr >;
 
 /** @brief Class representing a number in the AST */
 class ExprAstNumber : public ExprAst
@@ -1576,14 +1706,10 @@ class ExprAstVariable : public ExprAst
 class ExprAstFunctionVariable : public ExprAst
 {
   public:
-    ExprAstFunctionVariable(ExprAst *var, ExprAstList &&args)
-      : m_var(var), m_args(std::move(args))
+    ExprAstFunctionVariable(ExprAstPtr &&var, ExprAstList &&args)
+      : m_var(std::move(var)), m_args(std::move(args))
     { TRACE(("ExprAstFunctionVariable()\n"));
     }
-   ~ExprAstFunctionVariable()
-    {
-      delete m_var;
-    }
     virtual TemplateVariant resolve(TemplateContext *c)
     {
       std::vector<TemplateVariant> args;
@@ -1600,7 +1726,7 @@ class ExprAstFunctionVariable : public ExprAst
       return v;
     }
   private:
-    ExprAst *m_var = 0;
+    ExprAstPtr m_var;
     ExprAstList m_args;
 };
 
@@ -1608,9 +1734,8 @@ class ExprAstFunctionVariable : public ExprAst
 class ExprAstFilter : public ExprAst
 {
   public:
-    ExprAstFilter(const QCString &name,ExprAst *arg) : m_name(name), m_arg(arg)
+    ExprAstFilter(const QCString &name,ExprAstPtr &&arg) : m_name(name), m_arg(std::move(arg))
     { TRACE(("ExprAstFilter(%s)\n",name.data())); }
-   ~ExprAstFilter() { delete m_arg; }
     const QCString &name() const { return m_name; }
     TemplateVariant apply(const TemplateVariant &v,TemplateContext *c)
     {
@@ -1620,7 +1745,7 @@ class ExprAstFilter : public ExprAst
       TemplateVariant arg;
       if (m_arg) arg = m_arg->resolve(c);
       bool ok;
-      TemplateVariant result = TemplateFilterFactory::instance()->apply(m_name,v,arg,ok);
+      TemplateVariant result = TemplateFilterFactory::instance().apply(m_name,v,arg,ok);
       if (!ok)
       {
         ci->warn(ci->templateName(),ci->line(),"unknown filter '%s'",qPrint(m_name));
@@ -1629,24 +1754,25 @@ class ExprAstFilter : public ExprAst
     }
   private:
     QCString m_name;
-    ExprAst *m_arg = 0;
+    ExprAstPtr m_arg;
 };
 
+using ExprAstFilterPtr = std::unique_ptr<ExprAstFilter>;
+
 /** @brief Class representing a filter applied to an expression in the AST */
 class ExprAstFilterAppl : public ExprAst
 {
   public:
-    ExprAstFilterAppl(ExprAst *expr,ExprAstFilter *filter)
-      : m_expr(expr), m_filter(filter)
+    ExprAstFilterAppl(ExprAstPtr &&expr,ExprAstFilterPtr &&filter)
+      : m_expr(std::move(expr)), m_filter(std::move(filter))
     { TRACE(("ExprAstFilterAppl\n")); }
-   ~ExprAstFilterAppl() { delete m_expr; delete m_filter; }
     virtual TemplateVariant resolve(TemplateContext *c)
     {
       return m_filter->apply(m_expr->resolve(c),c);
     }
   private:
-    ExprAst *m_expr = 0;
-    ExprAstFilter *m_filter;
+    ExprAstPtr m_expr;
+    ExprAstFilterPtr m_filter;
 };
 
 /** @brief Class representing a string literal in the AST */
@@ -1665,45 +1791,42 @@ class ExprAstLiteral : public ExprAst
 class ExprAstNegate : public ExprAst
 {
   public:
-    ExprAstNegate(ExprAst *expr) : m_expr(expr)
+    ExprAstNegate(ExprAstPtr &&expr) : m_expr(std::move(expr))
     { TRACE(("ExprAstNegate\n")); }
-   ~ExprAstNegate() { delete m_expr; }
     virtual TemplateVariant resolve(TemplateContext *c)
     { return TemplateVariant(!m_expr->resolve(c).toBool()); }
   private:
-    ExprAst *m_expr = 0;
+    ExprAstPtr m_expr;
 };
 
 class ExprAstUnary : public ExprAst
 {
   public:
-    ExprAstUnary(Operator::Type op,ExprAst *exp) : m_operator(op), m_exp(exp)
+    ExprAstUnary(Operator::Type op,ExprAstPtr &&expr) : m_operator(op), m_expr(std::move(expr))
     { TRACE(("ExprAstUnary %s\n",Operator::toString(op))); }
-   ~ExprAstUnary() { delete m_exp; }
     virtual TemplateVariant resolve(TemplateContext *c)
     {
-      TemplateVariant exp = m_exp->resolve(c);
+      TemplateVariant expr = m_expr->resolve(c);
       switch (m_operator)
       {
         case Operator::Minus:
-          return -exp.toInt();
+          return -expr.toInt();
         default:
           return TemplateVariant();
       }
     }
   private:
     Operator::Type m_operator = Operator::Or;
-    ExprAst *m_exp = 0;
+    ExprAstPtr m_expr;
 };
 
 /** @brief Class representing a binary operator in the AST */
 class ExprAstBinary : public ExprAst
 {
   public:
-    ExprAstBinary(Operator::Type op,ExprAst *lhs,ExprAst *rhs)
-      : m_operator(op), m_lhs(lhs), m_rhs(rhs)
+    ExprAstBinary(Operator::Type op,ExprAstPtr &&lhs,ExprAstPtr &&rhs)
+      : m_operator(op), m_lhs(std::move(lhs)), m_rhs(std::move(rhs))
     { TRACE(("ExprAstBinary %s\n",Operator::toString(op))); }
-   ~ExprAstBinary() { delete m_lhs; delete m_rhs; }
     virtual TemplateVariant resolve(TemplateContext *c)
     {
       TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
@@ -1800,8 +1923,8 @@ class ExprAstBinary : public ExprAst
     }
   private:
     Operator::Type m_operator = Operator::Or;
-    ExprAst *m_lhs = 0;
-    ExprAst *m_rhs = 0;
+    ExprAstPtr m_lhs;
+    ExprAstPtr m_rhs;
 };
 
 //----------------------------------------------------------
@@ -1821,6 +1944,8 @@ class TemplateNode
     TemplateNode *m_parent = 0;
 };
 
+using TemplateNodePtr = std::unique_ptr<TemplateNode>;
+
 //----------------------------------------------------------
 
 /** @brief Class representing a lexical token in a template */
@@ -1840,7 +1965,7 @@ using TemplateTokenStream = std::deque< TemplateTokenPtr >;
 //----------------------------------------------------------
 
 /** @brief Class representing a list of AST nodes in a template */
-class TemplateNodeList : public std::vector< std::unique_ptr<TemplateNode> >
+class TemplateNodeList : public std::vector< TemplateNodePtr >
 {
   public:
     void render(TextStream &ts,TemplateContext *c)
@@ -1893,7 +2018,7 @@ class ExpressionParser
     {
     }
 
-    ExprAst *parse(const QCString &expr)
+    ExprAstPtr parse(const QCString &expr)
     {
       if (expr.isEmpty()) return 0;
       m_tokenStream = expr.data();
@@ -1921,65 +2046,65 @@ class ExpressionParser
         Operator::Type op;
     };
 
-    ExprAst *parseExpression()
+    ExprAstPtr parseExpression()
     {
       TRACE(("{parseExpression(%s)\n",m_tokenStream));
-      ExprAst *result = parseOrExpression();
+      ExprAstPtr result { parseOrExpression() };
       TRACE(("}parseExpression(%s)\n",m_tokenStream));
       return result;
     }
 
-    ExprAst *parseOrExpression()
+    ExprAstPtr parseOrExpression()
     {
       TRACE(("{parseOrExpression(%s)\n",m_tokenStream));
-      ExprAst *lhs = parseAndExpression();
+      ExprAstPtr lhs { parseAndExpression() };
       if (lhs)
       {
         while (m_curToken.type==ExprToken::Operator &&
             m_curToken.op==Operator::Or)
         {
           getNextToken();
-          ExprAst *rhs = parseAndExpression();
-          lhs = new ExprAstBinary(Operator::Or,lhs,rhs);
+          ExprAstPtr rhs { parseAndExpression() };
+          lhs = std::make_unique<ExprAstBinary>(Operator::Or,std::move(lhs),std::move(rhs));
         }
       }
       TRACE(("}parseOrExpression(%s)\n",m_tokenStream));
       return lhs;
     }
 
-    ExprAst *parseAndExpression()
+    ExprAstPtr parseAndExpression()
     {
       TRACE(("{parseAndExpression(%s)\n",m_tokenStream));
-      ExprAst *lhs = parseNotExpression();
+      ExprAstPtr lhs { parseNotExpression() };
       if (lhs)
       {
         while (m_curToken.type==ExprToken::Operator &&
                m_curToken.op==Operator::And)
         {
           getNextToken();
-          ExprAst *rhs = parseNotExpression();
-          lhs = new ExprAstBinary(Operator::And,lhs,rhs);
+          ExprAstPtr rhs { parseNotExpression() };
+          lhs = std::make_unique<ExprAstBinary>(Operator::And,std::move(lhs),std::move(rhs));
         }
       }
       TRACE(("}parseAndExpression(%s)\n",m_tokenStream));
       return lhs;
     }
 
-    ExprAst *parseNotExpression()
+    ExprAstPtr parseNotExpression()
     {
       TRACE(("{parseNotExpression(%s)\n",m_tokenStream));
-      ExprAst *result=0;
+      ExprAstPtr result;
       if (m_curToken.type==ExprToken::Operator &&
           m_curToken.op==Operator::Not)
       {
         getNextToken();
-        ExprAst *expr = parseCompareExpression();
+        ExprAstPtr expr = parseCompareExpression();
         if (expr==0)
         {
           warn(m_parser->templateName(),m_line,"argument missing for not operator");
           return 0;
         }
-        result = new ExprAstNegate(expr);
+        result = std::make_unique<ExprAstNegate>(std::move(expr));
       }
       else
       {
@@ -1989,10 +2114,10 @@ class ExpressionParser
       return result;
     }
 
-    ExprAst *parseCompareExpression()
+    ExprAstPtr parseCompareExpression()
     {
       TRACE(("{parseCompareExpression(%s)\n",m_tokenStream));
-      ExprAst *lhs = parseAdditiveExpression();
+      ExprAstPtr lhs { parseAdditiveExpression() };
       if (lhs)
       {
         Operator::Type op = m_curToken.op;
@@ -2007,18 +2132,18 @@ class ExpressionParser
            )
         {
           getNextToken();
-          ExprAst *rhs = parseNotExpression();
-          lhs = new ExprAstBinary(op,lhs,rhs);
+          ExprAstPtr rhs { parseNotExpression() };
+          lhs = std::make_unique<ExprAstBinary>(op,std::move(lhs),std::move(rhs));
         }
       }
       TRACE(("}parseCompareExpression(%s)\n",m_tokenStream));
       return lhs;
     }
 
-    ExprAst *parseAdditiveExpression()
+    ExprAstPtr parseAdditiveExpression()
     {
       TRACE(("{parseAdditiveExpression(%s)\n",m_tokenStream));
-      ExprAst *lhs = parseMultiplicativeExpression();
+      ExprAstPtr lhs { parseMultiplicativeExpression() };
       if (lhs)
       {
         while (m_curToken.type==ExprToken::Operator &&
@@ -2026,18 +2151,18 @@ class ExpressionParser
         {
           Operator::Type op = m_curToken.op;
           getNextToken();
-          ExprAst *rhs = parseMultiplicativeExpression();
-          lhs = new ExprAstBinary(op,lhs,rhs);
+          ExprAstPtr rhs { parseMultiplicativeExpression() };
+          lhs = std::make_unique<ExprAstBinary>(op,std::move(lhs),std::move(rhs));
         }
       }
       TRACE(("}parseAdditiveExpression(%s)\n",m_tokenStream));
       return lhs;
     }
 
-    ExprAst *parseMultiplicativeExpression()
+    ExprAstPtr parseMultiplicativeExpression()
     {
       TRACE(("{parseMultiplicativeExpression(%s)\n",m_tokenStream));
-      ExprAst *lhs = parseUnaryExpression();
+      ExprAstPtr lhs = parseUnaryExpression();
       if (lhs)
       {
         while (m_curToken.type==ExprToken::Operator &&
@@ -2045,18 +2170,18 @@ class ExpressionParser
         {
           Operator::Type op = m_curToken.op;
           getNextToken();
-          ExprAst *rhs = parseUnaryExpression();
-          lhs = new ExprAstBinary(op,lhs,rhs);
+          ExprAstPtr rhs = parseUnaryExpression();
+          lhs = std::make_unique<ExprAstBinary>(op,std::move(lhs),std::move(rhs));
         }
       }
       TRACE(("}parseMultiplicativeExpression(%s)\n",m_tokenStream));
       return lhs;
     }
 
-    ExprAst *parseUnaryExpression()
+    ExprAstPtr parseUnaryExpression()
     {
       TRACE(("{parseUnaryExpression(%s)\n",m_tokenStream));
-      ExprAst *result=0;
+      ExprAstPtr result;
       if (m_curToken.type==ExprToken::Operator)
       {
         if (m_curToken.op==Operator::Plus)
@@ -2067,8 +2192,8 @@ class ExpressionParser
         else if (m_curToken.op==Operator::Minus)
         {
           getNextToken();
-          ExprAst *rhs = parsePrimaryExpression();
-          result = new ExprAstUnary(m_curToken.op,rhs);
+          ExprAstPtr rhs { parsePrimaryExpression() };
+          result = std::make_unique<ExprAstUnary>(m_curToken.op,std::move(rhs));
         }
         else
         {
@@ -2083,10 +2208,10 @@ class ExpressionParser
       return result;
     }
 
-    ExprAst *parsePrimaryExpression()
+    ExprAstPtr parsePrimaryExpression()
     {
       TRACE(("{parsePrimary(%s)\n",m_tokenStream));
-      ExprAst *result=0;
+      ExprAstPtr result;
       switch (m_curToken.type)
       {
         case ExprToken::Number:
@@ -2127,37 +2252,37 @@ class ExpressionParser
       return result;
     }
 
-    ExprAst *parseNumber()
+    ExprAstPtr parseNumber()
     {
       TRACE(("{parseNumber(%d)\n",m_curToken.num));
-      ExprAst *num = new ExprAstNumber(m_curToken.num);
+      ExprAstPtr num = std::make_unique<ExprAstNumber>(m_curToken.num);
       getNextToken();
       TRACE(("}parseNumber()\n"));
       return num;
     }
 
-    ExprAst *parseIdentifier()
+    ExprAstPtr parseIdentifier()
     {
       TRACE(("{parseIdentifier(%s)\n",qPrint(m_curToken.id)));
-      ExprAst *id = new ExprAstVariable(m_curToken.id);
+      ExprAstPtr id = std::make_unique<ExprAstVariable>(m_curToken.id);
       getNextToken();
       TRACE(("}parseIdentifier()\n"));
       return id;
     }
 
-    ExprAst *parseLiteral()
+    ExprAstPtr parseLiteral()
     {
       TRACE(("{parseLiteral(%s)\n",qPrint(m_curToken.id)));
-      ExprAst *expr = new ExprAstLiteral(m_curToken.id);
+      ExprAstPtr expr = std::make_unique<ExprAstLiteral>(m_curToken.id);
       getNextToken();
       TRACE(("}parseLiteral()\n"));
       return expr;
     }
 
-    ExprAst *parseIdentifierOptionalArgs()
+    ExprAstPtr parseIdentifierOptionalArgs()
     {
       TRACE(("{parseIdentifierOptionalArgs(%s)\n",qPrint(m_curToken.id)));
-      ExprAst *expr = parseIdentifier();
+      ExprAstPtr expr { parseIdentifier() };
       if (expr)
       {
         if (m_curToken.type==ExprToken::Operator &&
@@ -2172,45 +2297,45 @@ class ExpressionParser
             getNextToken();
             args.push_back(std::unique_ptr<ExprAst>(parsePrimaryExpression()));
           }
-          expr = new ExprAstFunctionVariable(expr,std::move(args));
+          expr = std::make_unique<ExprAstFunctionVariable>(std::move(expr),std::move(args));
         }
       }
       TRACE(("}parseIdentifierOptionalArgs()\n"));
       return expr;
     }
 
-    ExprAst *parseFilteredVariable()
+    ExprAstPtr parseFilteredVariable()
     {
       TRACE(("{parseFilteredVariable()\n"));
-      ExprAst *expr = parseIdentifierOptionalArgs();
+      ExprAstPtr expr = parseIdentifierOptionalArgs();
       if (expr)
       {
         while (m_curToken.type==ExprToken::Operator &&
                m_curToken.op==Operator::Filter)
         {
           getNextToken();
-          ExprAstFilter *filter = parseFilter();
+          ExprAstFilterPtr filter = parseFilter();
           if (!filter) break;
-          expr = new ExprAstFilterAppl(expr,filter);
+          expr = std::make_unique<ExprAstFilterAppl>(std::move(expr),std::move(filter));
         }
       }
       TRACE(("}parseFilteredVariable()\n"));
       return expr;
     }
 
-    ExprAstFilter *parseFilter()
+    ExprAstFilterPtr parseFilter()
     {
       TRACE(("{parseFilter(%s)\n",qPrint(m_curToken.id)));
       QCString filterName = m_curToken.id;
       getNextToken();
-      ExprAst *argExpr=0;
+      ExprAstPtr argExpr;
       if (m_curToken.type==ExprToken::Operator &&
           m_curToken.op==Operator::Colon)
       {
         getNextToken();
         argExpr = parsePrimaryExpression();
       }
-      ExprAstFilter *filter = new ExprAstFilter(filterName,argExpr);
+      ExprAstFilterPtr filter = std::make_unique<ExprAstFilter>(filterName,std::move(argExpr));
       TRACE(("}parseFilter()\n"));
       return filter;
     }
@@ -2446,36 +2571,19 @@ class TemplateImpl : public TemplateNode, public Template
 
 //----------------------------------------------------------
 
-/** @brief Weak reference wrapper for TemplateStructIntf that provides access to the
- *  wrapped struct without holding a reference.
- */
-class TemplateStructWeakRef : public TemplateStructIntf
-{
-  public:
-    TemplateStructWeakRef(TemplateStructIntf *ref) : m_ref(ref), m_refCount(0) {}
-    virtual TemplateVariant get(const QCString &name) const { return m_ref->get(name); }
-    virtual StringVector fields() const { return m_ref->fields(); }
-    virtual int addRef() { return ++m_refCount; }
-    virtual int release() { int count=--m_refCount; if (count<=0) { delete this; } return count; }
-  private:
-    TemplateStructIntf *m_ref = 0;
-    int m_refCount = 0;
-};
-
-//----------------------------------------------------------
-
 TemplateContextImpl::TemplateContextImpl(const TemplateEngine *e)
-  : m_engine(e), m_templateName("<unknown>"), m_line(1), m_activeEscapeIntf(0),
-    m_spacelessIntf(0), m_spacelessEnabled(FALSE), m_tabbingEnabled(FALSE), m_indices(TemplateStruct::alloc())
+  : m_engine(e), m_indices(TemplateStruct::alloc())
 {
+  //printf("%p:TemplateContextImpl::TemplateContextImpl()\n",(void*)this);
   m_fromUtf8 = (void*)(-1);
   push();
-  set("index",m_indices.get());
+  set("index",std::static_pointer_cast<TemplateStructIntf>(m_indices));
 }
 
 TemplateContextImpl::~TemplateContextImpl()
 {
   pop();
+  //printf("%p:TemplateContextImpl::~TemplateContextImpl()\n",(void*)this);
 }
 
 void TemplateContextImpl::setEncoding(const QCString &templateName,int line,const QCString &enc)
@@ -2530,24 +2638,10 @@ void TemplateContextImpl::set(const QCString &name,const TemplateVariant &v)
     ctx.erase(it);
   }
   ctx.insert(std::make_pair(name.str(),v));
+  //printf("TemplateContextImpl::set(%s) #stacks=%lu front().size()=%lu\n",
+  //    qPrint(name),m_contextStack.size(),m_contextStack.size()>0 ? m_contextStack.front().size() : 0);
 }
 
-void TemplateContextImpl::update(const QCString &name,const TemplateVariant &v)
-{
-  int depth=0;
-  for (auto &ctx : m_contextStack)
-  {
-    auto it = ctx.find(name.str());
-    if (it!=ctx.end())
-    {
-      ctx.erase(it);
-      ctx.insert(std::make_pair(name.str(),v));
-      return;
-    }
-    depth++;
-  }
-  warn(m_templateName,m_line,"requesting update for non-existing variable '%s'",qPrint(name));
-}
 
 TemplateVariant TemplateContextImpl::get(const QCString &name) const
 {
@@ -2564,47 +2658,63 @@ TemplateVariant TemplateContextImpl::get(const QCString &name) const
     while (!propName.isEmpty())
     {
       //printf("getPrimary(%s) type=%zu:%s\n",qPrint(objName),v.type(),qPrint(v.toString()));
-      if (v.isStruct())
+      if (v.isStruct() || v.isWeakStruct())
       {
-        i = propName.find(".");
-        int l = i==-1 ? propName.length() : i;
-        v = v.toStruct()->get(propName.left(l));
-        if (!v.isValid())
-        {
-          warn(m_templateName,m_line,"requesting non-existing property '%s' for object '%s'",qPrint(propName.left(l)),qPrint(objName));
-        }
-        if (i!=-1)
+        TemplateStructIntfPtr s = v.toStruct();
+        if (s)
         {
-          objName = propName.left(i);
-          propName = propName.mid(i+1);
+          i = propName.find(".");
+          int l = i==-1 ? propName.length() : i;
+          v = s->get(propName.left(l));
+          if (!v.isValid())
+          {
+            warn(m_templateName,m_line,"requesting non-existing property '%s' for object '%s'",qPrint(propName.left(l)),qPrint(objName));
+          }
+          if (i!=-1)
+          {
+            objName = propName.left(i);
+            propName = propName.mid(i+1);
+          }
+          else
+          {
+            propName.resize(0);
+          }
         }
         else
         {
-          propName.resize(0);
+          return TemplateVariant();
         }
       }
       else if (v.isList())
       {
-        i = propName.find(".");
-        int l = i==-1 ? propName.length() : i;
-        bool b;
-        int index = propName.left(l).toInt(&b);
-        if (b)
-        {
-          v = v.toList()->at(index);
-        }
-        else
-        {
-          warn(m_templateName,m_line,"list index '%s' is not valid",qPrint(propName));
-          break;
-        }
-        if (i!=-1)
+        TemplateListIntfPtr list = v.toList();
+        if (list)
         {
-          propName = propName.mid(i+1);
+          i = propName.find(".");
+          int l = i==-1 ? propName.length() : i;
+          bool b;
+          int index = propName.left(l).toInt(&b);
+          if (b)
+          {
+            v = list->at(index);
+          }
+          else
+          {
+            warn(m_templateName,m_line,"list index '%s' is not valid",qPrint(propName));
+            break;
+          }
+          if (i!=-1)
+          {
+            propName = propName.mid(i+1);
+          }
+          else
+          {
+            propName.resize(0);
+          }
         }
         else
         {
-          propName.resize(0);
+          return TemplateVariant();
         }
       }
       else
@@ -2638,11 +2748,13 @@ TemplateVariant TemplateContextImpl::getPrimary(const QCString &name) const
 
 void TemplateContextImpl::push()
 {
-  m_contextStack.push_front(std::map<std::string,TemplateVariant>());
+  m_contextStack.push_front(std::unordered_map<std::string,TemplateVariant>());
+  //printf("TemplateContextImpl::push() #stacks=%lu\n",m_contextStack.size());
 }
 
 void TemplateContextImpl::pop()
 {
+  //printf("TemplateContextImpl::pop() #stacks=%lu\n",m_contextStack.size());
   if (m_contextStack.empty())
   {
     warn(m_templateName,m_line,"pop() called on empty context stack!\n");
@@ -2678,13 +2790,13 @@ void TemplateContextImpl::openSubIndex(const QCString &indexName)
   }
   // get the parent entry to add the list to
   auto &stack = kv->second;
-  TemplateStruct *entry = dynamic_cast<TemplateStruct*>(stack.top().toStruct());
+  TemplateStructPtr entry = std::dynamic_pointer_cast<TemplateStruct>(stack.top().toStruct());
   if (entry)
   {
     // add new list to the stack
-    TemplateList *list = TemplateList::alloc();
-    stack.emplace(list);
-    entry->set("children",list);
+    TemplateListPtr list = TemplateList::alloc();
+    stack.emplace(std::static_pointer_cast<TemplateListIntf>(list));
+    entry->set("children",std::static_pointer_cast<TemplateListIntf>(list));
     entry->set("is_leaf_node",false);
   }
 }
@@ -2700,7 +2812,7 @@ void TemplateContextImpl::closeSubIndex(const QCString &indexName)
   else
   {
     auto &stack = kv->second; // stack.size()>2
-    if (stack.top().isStruct())
+    if (stack.top().isStruct() || stack.top().isWeakStruct())
     {
       stack.pop(); // pop struct
       stack.pop(); // pop list
@@ -2708,7 +2820,7 @@ void TemplateContextImpl::closeSubIndex(const QCString &indexName)
     else // empty list! correct "is_left_node" attribute of the parent entry
     {
       stack.pop(); // pop list
-      TemplateStruct *entry = dynamic_cast<TemplateStruct*>(stack.top().toStruct());
+      TemplateStructPtr entry = std::dynamic_pointer_cast<TemplateStruct>(stack.top().toStruct());
       if (entry)
       {
         entry->set("is_leaf_node",true);
@@ -2718,28 +2830,30 @@ void TemplateContextImpl::closeSubIndex(const QCString &indexName)
   //fprintf(stderr,"TemplateContextImpl::closeSubIndex(%s) end g_count=%d\n\n",qPrint(indexName),g_count);
 }
 
-static void getPathListFunc(TemplateStructIntf *entry,TemplateList *list)
+static void getPathListFunc(const TemplateStructIntfPtr entry,TemplateListPtr list)
 {
-  TemplateVariant parent = entry->get("parent");
-  if (parent.isStruct())
+  if (entry)
   {
-    getPathListFunc(parent.toStruct(),list);
+    TemplateVariant parent = entry->get("parent");
+    if (parent.isStruct() || parent.isWeakStruct())
+    {
+      getPathListFunc(parent.toStruct(),list);
+    }
+    list->append(entry);
   }
-  list->append(entry);
 }
 
-static TemplateVariant getPathFunc(const void *ctx, const std::vector<TemplateVariant> &)
+static TemplateVariant getPathFunc(const TemplateStructIntfWeakPtr entryWeakRef)
 {
-  TemplateStruct *entry = (TemplateStruct*)ctx;
-  TemplateList *result = TemplateList::alloc();
-  getPathListFunc(entry,result);
-  return result;
+  TemplateListPtr result = TemplateList::alloc();
+  getPathListFunc(entryWeakRef.lock(),result);
+  return std::static_pointer_cast<TemplateListIntf>(result);
 }
 
 void TemplateContextImpl::addIndexEntry(const QCString &indexName,const std::vector<TemplateKeyValue> &arguments)
 {
-  auto it = arguments.begin();
-  //printf("TemplateContextImpl::addIndexEntry(%s)\n",qPrint(indexName));
+  //auto it = arguments.begin();
+  //printf("%p:> TemplateContextImpl::addIndexEntry(%s)\n",(void*)this,qPrint(indexName));
   //while (it!=arguments.end())
   //{
   //  printf("  key=%s value=%s\n",(*it).key.data(),(*it).value.toString().data());
@@ -2751,17 +2865,17 @@ void TemplateContextImpl::addIndexEntry(const QCString &indexName,const std::vec
   {
     kv = m_indexStacks.insert(std::make_pair(indexName.str(),std::stack<TemplateVariant>())).first;
   }
-  TemplateList *list  = 0;
+  TemplateListPtr list;
   auto &stack = kv->second;
   if (stack.empty()) // first item, create empty list and add it to the index
   {
     list = TemplateList::alloc();
-    stack.emplace(list);
-    m_indices->set(indexName,list); // make list available under index
+    stack.emplace(std::static_pointer_cast<TemplateListIntf>(list));
+    m_indices->set(indexName,std::static_pointer_cast<TemplateListIntf>(list)); // make list available under index
   }
   else // stack not empty
   {
-    if (stack.top().isStruct()) // already an entry in the list
+    if (stack.top().isStruct() || stack.top().isWeakStruct()) // already an entry in the list
     {
       // remove current entry from the stack
       stack.pop();
@@ -2776,22 +2890,21 @@ void TemplateContextImpl::addIndexEntry(const QCString &indexName,const std::vec
       stack.pop();
       // To prevent a cyclic dependency between parent and child which causes a memory
       // leak, we wrap the parent into a weak reference version.
-      parent = new TemplateStructWeakRef(stack.top().toStruct());
+      //parent = TemplateVariant(TemplateStructIntfWeakPtr(stack.top().toStruct()));
       stack.push(tmp);
-      ASSERT(parent.isStruct());
     }
     // get list to add new item
-    list = dynamic_cast<TemplateList*>(stack.top().toList());
+    list = std::dynamic_pointer_cast<TemplateList>(stack.top().toList());
   }
-  TemplateStruct *entry = TemplateStruct::alloc();
+  TemplateStructPtr entry = TemplateStruct::alloc();
   // add user specified fields to the entry
-  for (it=arguments.begin();it!=arguments.end();++it)
+  for (auto it=arguments.begin();it!=arguments.end();++it)
   {
     entry->set((*it).key,(*it).value);
   }
   if (list->count()>0)
   {
-    TemplateStruct *lastEntry = dynamic_cast<TemplateStruct*>(list->at(list->count()-1).toStruct());
+    TemplateStructPtr lastEntry = std::dynamic_pointer_cast<TemplateStruct>(list->at(list->count()-1).toStruct());
     if (lastEntry)
     {
       lastEntry->set("last",false);
@@ -2801,10 +2914,11 @@ void TemplateContextImpl::addIndexEntry(const QCString &indexName,const std::vec
   entry->set("first",list->count()==0);
   entry->set("index",list->count());
   entry->set("parent",parent);
-  entry->set("path",TemplateVariant::FunctionDelegate::fromFunction(entry,getPathFunc));
+  TemplateStructIntfWeakPtr entryWeak(std::static_pointer_cast<TemplateStructIntf>(entry));
+  entry->set("path",TemplateVariant([entryWeak](const TemplateVariantList &){ return getPathFunc(entryWeak); }));
   entry->set("last",true);
-  stack.emplace(entry);
-  list->append(entry);
+  stack.push(TemplateVariant(std::static_pointer_cast<TemplateStructIntf>(entry)));
+  list->append(TemplateVariant(std::static_pointer_cast<TemplateStructIntf>(entry)));
 }
 
 //----------------------------------------------------------
@@ -2870,11 +2984,11 @@ class TemplateNodeVariable : public TemplateNode
     }
     ~TemplateNodeVariable()
     {
-      delete m_var;
     }
 
     void render(TextStream &ts, TemplateContext *c)
     {
+      TRACE(("{TemplateNodeVariable::render\n"));
       TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
       if (ci==0) return; // should not happen
       ci->setLocation(m_templateName,m_line);
@@ -2883,7 +2997,7 @@ class TemplateNodeVariable : public TemplateNode
         TemplateVariant v = m_var->resolve(c);
         if (v.isFunction())
         {
-          v = v.call(std::vector<TemplateVariant>());
+          v = v.call();
         }
         if (ci->escapeIntf() && !v.raw())
         {
@@ -2908,12 +3022,13 @@ class TemplateNodeVariable : public TemplateNode
           }
         }
       }
+      TRACE(("}TemplateNodeVariable::render\n"));
     }
 
   private:
     QCString m_templateName;
     int m_line = 0;
-    ExprAst *m_var = 0;
+    ExprAstPtr m_var;
 };
 
 //----------------------------------------------------------
@@ -2926,12 +3041,12 @@ template<class T> class TemplateNodeCreator : public TemplateNode
   public:
     TemplateNodeCreator(TemplateParser *parser,TemplateNode *parent,int line)
       : TemplateNode(parent), m_templateName(parser->templateName()), m_line(line) {}
-    static TemplateNode *createInstance(TemplateParser *parser,
+    static TemplateNodePtr createInstance(TemplateParser *parser,
                                         TemplateNode *parent,
                                         int line,
                                         const QCString &data)
     {
-      return new T(parser,parent,line,data);
+      return std::make_unique<T>(parser,parent,line,data);
     }
     TemplateImpl *getTemplate()
     {
@@ -2943,7 +3058,7 @@ template<class T> class TemplateNodeCreator : public TemplateNode
       return dynamic_cast<TemplateImpl*>(root);
     }
   protected:
-    void mkpath(TemplateContextImpl *ci,const std::string &fileName)
+    void mkpath(const TemplateContextImpl *ci,const std::string &fileName)
     {
       size_t i=fileName.find('/');
       std::string outputDir = ci->outputDirectory().str();
@@ -3068,10 +3183,8 @@ class TemplateNodeIf : public TemplateNodeCreator<TemplateNodeIf>
   private:
     struct GuardedNodes
     {
-      GuardedNodes() : guardAst(0) {}
-     ~GuardedNodes() { delete guardAst; }
       int line = 0;
-      ExprAst *guardAst = 0;
+      ExprAstPtr guardAst;
       TemplateNodeList trueNodes;
     };
     std::vector< std::unique_ptr<GuardedNodes> > m_ifGuardedNodes;
@@ -3094,10 +3207,6 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat>
       parser->removeNextToken(); // skip over endrepeat
       TRACE(("}TemplateNodeRepeat(%s)\n",qPrint(data)));
     }
-    ~TemplateNodeRepeat()
-    {
-      delete m_expr;
-    }
     void render(TextStream &ts, TemplateContext *c)
     {
       TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
@@ -3109,14 +3218,14 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat>
         int i, n = v.toInt();
         for (i=0;i<n;i++)
         {
-          TemplateAutoRef<TemplateStruct> s(TemplateStruct::alloc());
+          TemplateStructPtr s = TemplateStruct::alloc();
           s->set("counter0",    (int)i);
           s->set("counter",     (int)(i+1));
           s->set("revcounter",  (int)(n-i));
           s->set("revcounter0", (int)(n-i-1));
           s->set("first",i==0);
           s->set("last", i==n-1);
-          c->set("repeatloop",s.get());
+          c->set("repeatloop",std::static_pointer_cast<TemplateStructIntf>(s));
           // render all items for this iteration of the loop
           m_repeatNodes.render(ts,c);
         }
@@ -3128,7 +3237,7 @@ class TemplateNodeRepeat : public TemplateNodeCreator<TemplateNodeRepeat>
     }
   private:
     TemplateNodeList m_repeatNodes;
-    ExprAst *m_expr = 0;
+    ExprAstPtr m_expr;
 };
 
 //----------------------------------------------------------
@@ -3147,7 +3256,7 @@ class TemplateNodeRange : public TemplateNodeCreator<TemplateNodeRange>
       int i3 = data.find(" downto ");
       if (i1==-1)
       {
-        if (data.right(5)==" from")
+        if (data.endsWith(" from"))
         {
           parser->warn(m_templateName,line,"range missing after 'from' keyword");
         }
@@ -3162,11 +3271,11 @@ class TemplateNodeRange : public TemplateNodeCreator<TemplateNodeRange>
       }
       else if (i2==-1 && i3==-1)
       {
-        if (data.right(3)==" to")
+        if (data.endsWith(" to"))
         {
           parser->warn(m_templateName,line,"range is missing end value after 'to' keyword");
         }
-        else if (data.right(7)==" downto")
+        else if (data.endsWith(" downto"))
         {
           parser->warn(m_templateName,line,"range is missing end value after 'downto' keyword");
         }
@@ -3204,12 +3313,6 @@ class TemplateNodeRange : public TemplateNodeCreator<TemplateNodeRange>
       TRACE(("}TemplateNodeRange(%s)\n",qPrint(data)));
     }
 
-    ~TemplateNodeRange()
-    {
-      delete m_startExpr;
-      delete m_endExpr;
-    }
-
     void render(TextStream &ts, TemplateContext *c)
     {
       TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
@@ -3237,7 +3340,7 @@ class TemplateNodeRange : public TemplateNodeCreator<TemplateNodeRange>
             while (!done)
             {
               // set the forloop meta-data variable
-              TemplateAutoRef<TemplateStruct> ls(TemplateStruct::alloc());
+              TemplateStructPtr ls = TemplateStruct::alloc();
               ls->set("counter0",    (int)index);
               ls->set("counter",     (int)(index+1));
               ls->set("revcounter",  (int)(l-index));
@@ -3245,7 +3348,7 @@ class TemplateNodeRange : public TemplateNodeCreator<TemplateNodeRange>
               ls->set("first",index==0);
               ls->set("last", (int)index==l-1);
               ls->set("parentloop",parentLoop ? *parentLoop : TemplateVariant());
-              c->set("forloop",ls.get());
+              c->set("forloop",std::static_pointer_cast<TemplateStructIntf>(ls));
 
               // set the iterator variable
               c->set(m_var,i);
@@ -3294,8 +3397,8 @@ class TemplateNodeRange : public TemplateNodeCreator<TemplateNodeRange>
 
   private:
     bool m_down = false;
-    ExprAst *m_startExpr = 0;
-    ExprAst *m_endExpr = 0;
+    ExprAstPtr m_startExpr;
+    ExprAstPtr m_endExpr;
     QCString m_var;
     TemplateNodeList m_loopNodes;
 };
@@ -3314,7 +3417,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
       int i = data.find(" in ");
       if (i==-1)
       {
-        if (data.right(3)==" in")
+        if (data.endsWith(" in"))
         {
           parser->warn(m_templateName,line,"for is missing container after 'in' keyword");
         }
@@ -3363,11 +3466,6 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
       TRACE(("}TemplateNodeFor(%s)\n",qPrint(data)));
     }
 
-    ~TemplateNodeFor()
-    {
-      delete m_expr;
-    }
-
     void render(TextStream &ts, TemplateContext *c)
     {
       TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
@@ -3380,9 +3478,9 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
         TemplateVariant v = m_expr->resolve(c);
         if (v.isFunction())
         {
-          v = v.call(std::vector<TemplateVariant>());
+          v = v.call();
         }
-        const TemplateListIntf *list = v.toList();
+        const TemplateListIntfPtr list = v.toList();
         if (list)
         {
           uint listSize = list->count();
@@ -3396,13 +3494,13 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
           //TemplateVariant v;
           const TemplateVariant *parentLoop = c->getRef("forloop");
           uint index = m_reversed ? listSize-1 : 0;
-          TemplateListIntf::ConstIterator *it = list->createIterator();
+          TemplateListIntf::ConstIteratorPtr it = list->createIterator();
           TemplateVariant ve;
           for (m_reversed ? it->toLast() : it->toFirst();
               (it->current(ve));
               m_reversed ? it->toPrev() : it->toNext())
           {
-            TemplateAutoRef<TemplateStruct> s(TemplateStruct::alloc());
+            TemplateStructPtr s = TemplateStruct::alloc();
             s->set("counter0",    (int)index);
             s->set("counter",     (int)(index+1));
             s->set("revcounter",  (int)(listSize-index));
@@ -3410,7 +3508,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
             s->set("first",index==0);
             s->set("last", index==listSize-1);
             s->set("parentloop",parentLoop ? *parentLoop : TemplateVariant());
-            c->set("forloop",s.get());
+            c->set("forloop",std::static_pointer_cast<TemplateStructIntf>(s));
 
             // add variables for this loop to the context
             //obj->addVariableToContext(index,m_vars,c);
@@ -3419,12 +3517,16 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
             {
               c->set(m_vars[vi++],ve);
             }
-            else if (m_vars.size()>1 && ve.isStruct())
+            else if (m_vars.size()>1 && (ve.isStruct() || ve.isWeakStruct()))
               // loop variables represent elements in a list item
             {
-              for (uint i=0;i<m_vars.size();i++,vi++)
+              TemplateStructIntfPtr vs = ve.toStruct();
+              if (vs)
               {
-                c->set(m_vars[vi],ve.toStruct()->get(m_vars[vi]));
+                for (uint i=0;i<m_vars.size();i++,vi++)
+                {
+                  c->set(m_vars[vi],vs->get(m_vars[vi]));
+                }
               }
             }
             for (;vi<m_vars.size();vi++)
@@ -3438,7 +3540,6 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
             if (m_reversed) index--; else index++;
           }
           c->pop();
-          delete it;
         }
         else // simple type...
         {
@@ -3449,7 +3550,7 @@ class TemplateNodeFor : public TemplateNodeCreator<TemplateNodeFor>
 
   private:
     bool m_reversed = false;
-    ExprAst *m_expr = 0;
+    ExprAstPtr m_expr;
     std::vector<QCString> m_vars;
     TemplateNodeList m_loopNodes;
     TemplateNodeList m_emptyNodes;
@@ -3472,6 +3573,7 @@ class TemplateNodeMsg : public TemplateNodeCreator<TemplateNodeMsg>
     }
     void render(TextStream &, TemplateContext *c)
     {
+      TRACE(("{TemplateNodeMsg::render\n"));
       TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
       if (ci==0) return; // should not happen
       ci->setLocation(m_templateName,m_line);
@@ -3485,6 +3587,7 @@ class TemplateNodeMsg : public TemplateNodeCreator<TemplateNodeMsg>
       std::cout << "\n";
       ci->setActiveEscapeIntf(escIntf);
       ci->enableSpaceless(enable);
+      TRACE(("}TemplateNodeMsg::render\n"));
     }
   private:
     TemplateNodeList m_nodes;
@@ -3538,9 +3641,9 @@ class TemplateNodeBlock : public TemplateNodeCreator<TemplateNodeBlock>
           }
           QCString super = ss.str();
           // add 'block.super' variable to allow access to parent block content
-          TemplateAutoRef<TemplateStruct> superBlock(TemplateStruct::alloc());
+          TemplateStructPtr superBlock = TemplateStruct::alloc();
           superBlock->set("super",TemplateVariant(super.data(),TRUE));
-          ci->set("block",superBlock.get());
+          ci->set("block",std::static_pointer_cast<TemplateStructIntf>(superBlock));
           // render the overruled block contents
           t->engine()->enterBlock(nb->m_templateName,nb->m_blockName,nb->m_line);
           nb->m_nodes.render(ts,c);
@@ -3588,10 +3691,6 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend>
       parser->parse(this,line,stopAt,m_nodes);
       TRACE(("}TemplateNodeExtend(%s)\n",qPrint(data)));
     }
-   ~TemplateNodeExtend()
-    {
-      delete m_extendExpr;
-    }
 
     void render(TextStream &ts, TemplateContext *c)
     {
@@ -3637,17 +3736,17 @@ class TemplateNodeExtend : public TemplateNodeCreator<TemplateNodeExtend>
 
           // clean up
           bc->clear();
-          t->engine()->unload(t);
         }
         else
         {
           ci->warn(m_templateName,m_line,"failed to load template %s for extend",qPrint(extendFile));
         }
+        t->engine()->unload(bt);
       }
     }
 
   private:
-    ExprAst *m_extendExpr = 0;
+    ExprAstPtr m_extendExpr;
     TemplateNodeList m_nodes;
 };
 
@@ -3666,10 +3765,6 @@ class TemplateNodeInclude : public TemplateNodeCreator<TemplateNodeInclude>
       }
       m_includeExpr = ep.parse(data);
     }
-   ~TemplateNodeInclude()
-    {
-      delete m_includeExpr;
-    }
     void render(TextStream &ts, TemplateContext *c)
     {
       TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
@@ -3692,35 +3787,36 @@ class TemplateNodeInclude : public TemplateNodeCreator<TemplateNodeInclude>
             if (incTemplate)
             {
               incTemplate->render(ts,c);
-              t->engine()->unload(t);
             }
             else
             {
               ci->warn(m_templateName,m_line,"failed to load template '%s' for include",qPrint(includeFile));
             }
+            t->engine()->unload(it);
           }
         }
       }
     }
 
   private:
-    ExprAst *m_includeExpr = 0;
+    ExprAstPtr m_includeExpr;
 };
 
 //----------------------------------------------------------
 
 static void stripLeadingWhiteSpace(QCString &s)
 {
-  uint i=0, dstIdx=0, l=s.length();
   bool skipSpaces=true;
-  while (i<l)
+  const char *src = s.data();
+  char *dst = s.rawData();
+  char c;
+  while ((c=*src++))
   {
-    char c = s[i++];
-    if (c=='\n') { s[dstIdx++]=c; skipSpaces=true; }
+    if (c=='\n') { *dst++=c; skipSpaces=true; }
     else if (c==' ' && skipSpaces) {}
-    else { s[dstIdx++] = c; skipSpaces=false; }
+    else { *dst++ = c; skipSpaces=false; }
   }
-  s.resize(dstIdx+1);
+  s.resize(dst-s.data()+1);
 }
 
 /** @brief Class representing an 'create' tag in a template */
@@ -3728,7 +3824,7 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
 {
   public:
     TemplateNodeCreate(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data)
-      : TemplateNodeCreator<TemplateNodeCreate>(parser,parent,line), m_templateExpr(0), m_fileExpr(0)
+      : TemplateNodeCreator<TemplateNodeCreate>(parser,parent,line)
     {
       TRACE(("TemplateNodeCreate(%s)\n",qPrint(data)));
       if (data.isEmpty())
@@ -3738,7 +3834,7 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
       int i = data.find(" from ");
       if (i==-1)
       {
-        if (data.right(3)==" from")
+        if (data.endsWith(" from"))
         {
           parser->warn(m_templateName,line,"create is missing template name after 'from' keyword");
         }
@@ -3758,13 +3854,9 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
         m_templateExpr = ep.parse(data.mid(i+6).stripWhiteSpace());
       }
     }
-   ~TemplateNodeCreate()
-    {
-      delete m_templateExpr;
-      delete m_fileExpr;
-    }
     void render(TextStream &, TemplateContext *c)
     {
+      TRACE(("{TemplateNodeCreate::render\n"));
       TemplateContextImpl* ci = dynamic_cast<TemplateContextImpl*>(c);
       if (ci==0) return; // should not happen
       ci->setLocation(m_templateName,m_line);
@@ -3829,11 +3921,12 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
           }
         }
       }
+      TRACE(("}TemplateNodeCreate::render\n"));
     }
 
   private:
-    ExprAst *m_templateExpr = 0;
-    ExprAst *m_fileExpr = 0;
+    ExprAstPtr m_templateExpr;
+    ExprAstPtr m_fileExpr;
 };
 
 //----------------------------------------------------------
@@ -3843,10 +3936,10 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree>
 {
     struct TreeContext
     {
-      TreeContext(TemplateNodeTree *o,const TemplateListIntf *l,TemplateContext *c)
+      TreeContext(TemplateNodeTree *o,const TemplateListIntfPtr l,TemplateContext *c)
         : object(o), list(l), templateCtx(c) {}
       TemplateNodeTree *object;
-      const TemplateListIntf *list;
+      const TemplateListIntfPtr list;
       TemplateContext  *templateCtx;
     };
   public:
@@ -3865,15 +3958,6 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree>
       parser->removeNextToken(); // skip over endrecursetree
       TRACE(("}TemplateNodeTree(%s)\n",qPrint(data)));
     }
-    ~TemplateNodeTree()
-    {
-      delete m_treeExpr;
-    }
-    static TemplateVariant renderChildrenStub(const void *ctx, const std::vector<TemplateVariant> &)
-    {
-      return TemplateVariant(((TreeContext*)ctx)->object->
-                             renderChildren((const TreeContext*)ctx),TRUE);
-    }
     QCString renderChildren(const TreeContext *ctx)
     {
       //printf("TemplateNodeTree::renderChildren(%d)\n",ctx->list->count());
@@ -3884,22 +3968,25 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree>
       TextStream ss;
       c->push();
       TemplateVariant node;
-      TemplateListIntf::ConstIterator *it = ctx->list->createIterator();
+      TemplateListIntf::ConstIteratorPtr it = ctx->list->createIterator();
       for (it->toFirst();(it->current(node));it->toNext())
       {
         c->set("node",node);
         bool hasChildren=FALSE;
-        const TemplateStructIntf *ns = node.toStruct();
+        const TemplateStructIntfPtr ns = node.toStruct();
         if (ns) // node is a struct
         {
           TemplateVariant v = ns->get("children");
           if (v.isValid()) // with a field 'children'
           {
-            const TemplateListIntf *list = v.toList();
+            const TemplateListIntfPtr list = v.toList();
             if (list && list->count()>0) // non-empty list
             {
               TreeContext childCtx(this,list,ctx->templateCtx);
-              TemplateVariant children(TemplateVariant::FunctionDelegate::fromFunction(&childCtx,renderChildrenStub));
+              TemplateVariant children(
+                    [childCtx](const TemplateVariantList &) {
+                       return TemplateVariant(childCtx.object->renderChildren(&childCtx),TRUE);
+                    });
               children.setRaw(TRUE);
               c->set("children",children);
               m_treeNodes.render(ss,c);
@@ -3922,7 +4009,6 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree>
         }
       }
       c->pop();
-      delete it;
       return ss.str();
     }
     void render(TextStream &ts, TemplateContext *c)
@@ -3932,7 +4018,7 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree>
       if (ci==0) return; // should not happen
       ci->setLocation(m_templateName,m_line);
       TemplateVariant v = m_treeExpr->resolve(c);
-      const TemplateListIntf *list = v.toList();
+      const TemplateListIntfPtr list = v.toList();
       if (list)
       {
         TreeContext ctx(this,list,c);
@@ -3945,7 +4031,7 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree>
     }
 
   private:
-    ExprAst         *m_treeExpr = 0;
+    ExprAstPtr       m_treeExpr;
     TemplateNodeList m_treeNodes;
 };
 
@@ -3958,7 +4044,7 @@ class TemplateNodeIndexEntry : public TemplateNodeCreator<TemplateNodeIndexEntry
     {
       Mapping(const QCString &n,std::unique_ptr<ExprAst> &&e) : name(n), value(std::move(e)) {}
       QCString name;
-      std::unique_ptr<ExprAst> value = 0;
+      ExprAstPtr value;
     };
   public:
     TemplateNodeIndexEntry(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data)
@@ -3982,10 +4068,10 @@ class TemplateNodeIndexEntry : public TemplateNodeCreator<TemplateNodeIndexEntry
           int j=arg.find('=');
           if (j>0)
           {
-            ExprAst *expr = expParser.parse(arg.mid(j+1));
+            ExprAstPtr expr = expParser.parse(arg.mid(j+1));
             if (expr)
             {
-              m_args.emplace_back(arg.left(j),std::unique_ptr<ExprAst>(expr));
+              m_args.emplace_back(arg.left(j),std::move(expr));
             }
           }
           else
@@ -4097,9 +4183,9 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith>
 {
     struct Mapping
     {
-      Mapping(const QCString &n,std::unique_ptr<ExprAst> &&e) : name(n), value(std::move(e)) {}
+      Mapping(const QCString &n,ExprAstPtr &&e) : name(n), value(std::move(e)) {}
       QCString name;
-      std::unique_ptr<ExprAst> value;
+      ExprAstPtr value;
     };
   public:
     TemplateNodeWith(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data)
@@ -4117,10 +4203,10 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith>
         int j=arg.find('=');
         if (j>0)
         {
-          ExprAst *expr = expParser.parse(arg.mid(j+1));
+          ExprAstPtr expr = expParser.parse(arg.mid(j+1));
           if (expr)
           {
-            m_args.emplace_back(arg.left(j),std::unique_ptr<ExprAst>(expr));
+            m_args.emplace_back(arg.left(j),std::move(expr));
           }
         }
         else
@@ -4172,10 +4258,10 @@ class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle>
       auto it = args.begin();
       while (it!=args.end())
       {
-        ExprAst *expr = expParser.parse(*it);
+        ExprAstPtr expr = expParser.parse(*it);
         if (expr)
         {
-          m_args.push_back(std::unique_ptr<ExprAst>(expr));
+          m_args.emplace_back(std::move(expr));
         }
         ++it;
       }
@@ -4195,7 +4281,7 @@ class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle>
         TemplateVariant v = m_args[m_index]->resolve(c);
         if (v.isFunction())
         {
-          v = v.call(std::vector<TemplateVariant>());
+          v = v.call();
         }
         if (ci->escapeIntf() && !v.raw())
         {
@@ -4237,10 +4323,9 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet>
 {
     struct Mapping
     {
-      Mapping(const QCString &n,ExprAst *e) : name(n), value(e) {}
-     ~Mapping() { delete value; }
+      Mapping(const QCString &n,ExprAstPtr &&e) : name(n), value(std::move(e)) {}
       QCString name;
-      ExprAst *value = 0;
+      ExprAstPtr value;
     };
   public:
     TemplateNodeSet(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data)
@@ -4250,10 +4335,10 @@ class TemplateNodeSet : public TemplateNodeCreator<TemplateNodeSet>
       ExpressionParser expParser(parser,line);
       // data format: name=expression
       int j=data.find('=');
-      ExprAst *expr = 0;
+      ExprAstPtr expr = 0;
       if (j>0 && (expr = expParser.parse(data.mid(j+1))))
       {
-        m_mapping = std::make_unique<Mapping>(data.left(j),expr);
+        m_mapping = std::make_unique<Mapping>(data.left(j),std::move(expr));
       }
       TRACE(("}TemplateNodeSet(%s)\n",qPrint(data)));
     }
@@ -4311,7 +4396,7 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
 {
   public:
     TemplateNodeMarkers(TemplateParser *parser,TemplateNode *parent,int line,const QCString &data)
-      : TemplateNodeCreator<TemplateNodeMarkers>(parser,parent,line), m_listExpr(0), m_patternExpr(0)
+      : TemplateNodeCreator<TemplateNodeMarkers>(parser,parent,line)
     {
       TRACE(("{TemplateNodeMarkers(%s)\n",qPrint(data)));
       int i = data.find(" in ");
@@ -4332,11 +4417,6 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
       parser->removeNextToken(); // skip over endmarkers
       TRACE(("}TemplateNodeMarkers(%s)\n",qPrint(data)));
     }
-   ~TemplateNodeMarkers()
-    {
-      delete m_listExpr;
-      delete m_patternExpr;
-    }
     void render(TextStream &ts, TemplateContext *c)
     {
       TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
@@ -4345,13 +4425,13 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
       if (!m_var.isEmpty() && m_listExpr && m_patternExpr)
       {
         TemplateVariant v = m_listExpr->resolve(c);
-        const TemplateListIntf *list = v.toList();
+        const TemplateListIntfPtr list = v.toList();
         TemplateVariant patternStr = m_patternExpr->resolve(c);
         if (list)
         {
           if (patternStr.isString())
           {
-            TemplateListIntf::ConstIterator *it = list->createIterator();
+            TemplateListIntf::ConstIteratorPtr it = list->createIterator();
             c->push();
             std::string str = patternStr.toString().str();
 
@@ -4380,9 +4460,9 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
               for (it->toFirst(); (it->current(var)) && i<entryIndex; it->toNext(),i++) {}
               if (i==entryIndex) // found element
               {
-                TemplateAutoRef<TemplateStruct> s(TemplateStruct::alloc());
+                TemplateStructPtr s = TemplateStruct::alloc();
                 s->set("id",(int)i);
-                c->set("markers",s.get());
+                c->set("markers",std::static_pointer_cast<TemplateStructIntf>(s));
                 c->set(m_var,var); // define local variable to hold element of list type
                 bool wasSpaceless = ci->spacelessEnabled();
                 ci->enableSpaceless(TRUE);
@@ -4404,7 +4484,6 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
               ts << str.substr(index); // write text after last marker
             }
             c->pop();
-            delete it;
           }
           else
           {
@@ -4420,8 +4499,8 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
   private:
     TemplateNodeList m_nodes;
     QCString m_var;
-    ExprAst *m_listExpr = 0;
-    ExprAst *m_patternExpr = 0;
+    ExprAstPtr m_listExpr;
+    ExprAstPtr m_patternExpr;
 };
 
 //----------------------------------------------------------
@@ -4468,8 +4547,8 @@ class TemplateNodeResource : public TemplateNodeCreator<TemplateNodeResource>
       if (data.isEmpty())
       {
         parser->warn(m_templateName,line,"resource tag is missing resource file argument");
-        m_resExpr=0;
-        m_asExpr=0;
+        m_resExpr.reset();
+        m_asExpr.reset();
       }
       else if ((i=data.find(" as "))!=-1) // resource a as b
       {
@@ -4485,15 +4564,10 @@ class TemplateNodeResource : public TemplateNodeCreator<TemplateNodeResource>
       else // resource a
       {
         m_resExpr = ep.parse(data);
-        m_asExpr  = 0;
+        m_asExpr.reset();
       }
       TRACE(("}TemplateNodeResource(%s)\n",qPrint(data)));
     }
-    ~TemplateNodeResource()
-    {
-      delete m_resExpr;
-      delete m_asExpr;
-    }
     void render(TextStream &, TemplateContext *c)
     {
       TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
@@ -4530,8 +4604,8 @@ class TemplateNodeResource : public TemplateNodeCreator<TemplateNodeResource>
       }
     }
   private:
-    ExprAst *m_resExpr = 0;
-    ExprAst *m_asExpr = 0;
+    ExprAstPtr m_resExpr;
+    ExprAstPtr m_asExpr;
     bool m_append = false;
 };
 
@@ -4549,7 +4623,7 @@ class TemplateNodeEncoding : public TemplateNodeCreator<TemplateNodeEncoding>
       if (data.isEmpty())
       {
         parser->warn(m_templateName,line,"encoding tag is missing encoding argument");
-        m_encExpr = 0;
+        m_encExpr.reset();
       }
       else
       {
@@ -4560,10 +4634,6 @@ class TemplateNodeEncoding : public TemplateNodeCreator<TemplateNodeEncoding>
       parser->removeNextToken(); // skip over endencoding
       TRACE(("}TemplateNodeEncoding(%s)\n",qPrint(data)));
     }
-   ~TemplateNodeEncoding()
-    {
-      delete m_encExpr;
-    }
     void render(TextStream &ts, TemplateContext *c)
     {
       TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
@@ -4583,7 +4653,7 @@ class TemplateNodeEncoding : public TemplateNodeCreator<TemplateNodeEncoding>
       ci->setEncoding(m_templateName,m_line,oldEncStr);
     }
   private:
-    ExprAst *m_encExpr;
+    ExprAstPtr m_encExpr;
     TemplateNodeList m_nodes;
 };
 
@@ -4593,19 +4663,19 @@ class TemplateNodeEncoding : public TemplateNodeCreator<TemplateNodeEncoding>
 class TemplateNodeFactory
 {
   public:
-    typedef TemplateNode *(*CreateFunc)(TemplateParser *parser,
+    typedef TemplateNodePtr (*CreateFunc)(TemplateParser *parser,
                                         TemplateNode *parent,
                                         int line,
                                         const QCString &data);
 
-    static TemplateNodeFactory *instance()
+    static TemplateNodeFactory &instance()
     {
-      static TemplateNodeFactory *instance = 0;
-      if (instance==0) instance = new TemplateNodeFactory;
-      return instance;
+      static std::unique_ptr<TemplateNodeFactory> instance;
+      if (instance==0) instance = std::make_unique<TemplateNodeFactory>();
+      return *instance;
     }
 
-    TemplateNode *create(const QCString &name,
+    TemplateNodePtr create(const QCString &name,
                          TemplateParser *parser,
                          TemplateNode *parent,
                          int line,
@@ -4627,7 +4697,7 @@ class TemplateNodeFactory
       public:
         AutoRegister<T>(const QCString &key)
         {
-          TemplateNodeFactory::instance()->registerTemplateNode(key,T::createInstance);
+          TemplateNodeFactory::instance().registerTemplateNode(key,T::createInstance);
         }
     };
 
@@ -5023,8 +5093,8 @@ void TemplateParser::parse(
           {
             arg = tok_ptr->data.mid(sep+1);
           }
-          std::unique_ptr<TemplateNode> node { TemplateNodeFactory::instance()->
-                               create(command,this,parent,tok_ptr->line,arg) };
+          TemplateNodePtr node = TemplateNodeFactory::instance().create(
+                                 command,this,parent,tok_ptr->line,arg);
           if (node)
           {
             nodes.push_back(std::move(node));
@@ -5108,6 +5178,7 @@ TemplateImpl::TemplateImpl(TemplateEngine *engine,const QCString &name,const QCS
     const QCString &extension)
   : TemplateNode(0)
 {
+  //printf("%p:TemplateImpl::TemplateImpl(%s)\n",(void*)this,qPrint(name));
   m_name = name;
   m_engine = engine;
   TemplateLexer lexer(engine,name,data);
@@ -5123,7 +5194,7 @@ TemplateImpl::TemplateImpl(TemplateEngine *engine,const QCString &name,const QCS
 
 TemplateImpl::~TemplateImpl()
 {
-  //printf("deleting template %s\n",qPrint(m_name));
+  //printf("%p:TemplateImpl::~TemplateImpl(%s)\n",(void*)this,qPrint(m_name));
 }
 
 void TemplateImpl::render(TextStream &ts, TemplateContext *c)
@@ -5174,6 +5245,11 @@ class TemplateEngine::Private
   public:
     Private(TemplateEngine *engine) : m_engine(engine)
     {
+      //printf("%p:TemplateEngine::Private::Private()\n",(void*)this);
+    }
+    ~Private()
+    {
+      //printf("%p:TemplateEngine::Private::~Private()\n",(void*)this);
     }
     Template *loadByName(const QCString &fileName,int line)
     {
@@ -5289,24 +5365,17 @@ class TemplateEngine::Private
     QCString m_templateDirName;
 };
 
-TemplateEngine::TemplateEngine()
+TemplateEngine::TemplateEngine() : p(std::make_unique<Private>(this))
 {
-  p = new Private(this);
 }
 
 TemplateEngine::~TemplateEngine()
 {
-  delete p;
-}
-
-TemplateContext *TemplateEngine::createContext() const
-{
-  return new TemplateContextImpl(this);
 }
 
-void TemplateEngine::destroyContext(TemplateContext *ctx)
+std::unique_ptr<TemplateContext> TemplateEngine::createContext() const
 {
-  delete ctx;
+  return std::make_unique<TemplateContextImpl>(this);
 }
 
 Template *TemplateEngine::loadByName(const QCString &fileName,int line)
@@ -5354,19 +5423,18 @@ void TemplateEngine::setTemplateDir(const QCString &dirName)
 QCString TemplateVariant::listToString() const
 {
   QCString result="[";
-  const TemplateListIntf *list = toList();
+  const TemplateListIntfPtr list = toList();
   if (list)
   {
     bool first=true;
     TemplateVariant ve;
-    TemplateListIntf::ConstIterator *it = list->createIterator();
+    TemplateListIntf::ConstIteratorPtr it = list->createIterator();
     for (it->toFirst();it->current(ve);it->toNext())
     {
       if (!first) result+=",\n";
       result+="'"+ve.toString()+"'";
       first=false;
     }
-    delete it;
   }
   result+="]";
   return result;
@@ -5375,7 +5443,7 @@ QCString TemplateVariant::listToString() const
 QCString TemplateVariant::structToString() const
 {
   QCString result="{";
-  const TemplateStructIntf *strukt = toStruct();
+  const TemplateStructIntfPtr strukt = toStruct();
   if (strukt)
   {
     bool first=true;
@@ -5383,7 +5451,7 @@ QCString TemplateVariant::structToString() const
     {
       if (!first) result+=",";
       result+=s;
-      if (dynamic_cast<const TemplateStructWeakRef*>(strukt)==0) // avoid endless recursion
+      if (!isWeakStruct()) // avoid endless recursion
       {
         result+=":'";
         result+=strukt->get(QCString(s)).toString();
index ba421b4..4c9f89b 100644 (file)
@@ -17,6 +17,8 @@
 #define TEMPLATE_H
 
 #include <vector>
+#include <memory>
+#include <functional>
 
 #include "qcstring.h"
 #include "containers.h"
@@ -27,6 +29,10 @@ class TemplateStructIntf;
 class TemplateEngine;
 class TextStream;
 
+using TemplateListIntfPtr       = std::shared_ptr<TemplateListIntf>;
+using TemplateStructIntfPtr     = std::shared_ptr<TemplateStructIntf>;
+using TemplateStructIntfWeakPtr = std::weak_ptr<TemplateStructIntf>;
+
 /** @defgroup template_api Template API
  *
  *  This is the API for a
@@ -92,78 +98,63 @@ class TextStream;
 class TemplateVariant
 {
   public:
-    /** @brief Helper class to create a delegate that can store a function/method call. */
-    class FunctionDelegate
+    /** Type representing a function call in a template */
+    using FunctionDelegate = std::function<TemplateVariant(const std::vector<TemplateVariant>&)>;
+
+    /** Symbolic names for the possible types that this variant can hold. */
+    using VariantT = Variant<bool,                      // index==0: Type::Bool
+                             int,                       // index==1: Type::Int
+                             QCString,                  // index==2: Type::String
+                             TemplateStructIntfPtr,     // index==3: Type::Struct
+                             TemplateListIntfPtr,       // index==4: Type::List
+                             FunctionDelegate,          // index==5: Type::Function
+                             TemplateStructIntfWeakPtr  // index==6: Type::WeakStruct
+                            >;
+
+    enum class Type : uint8_t
     {
-      public:
-        /** Callback type to use when creating a delegate from a function. */
-        typedef TemplateVariant (*StubType)(const void *obj, const std::vector<TemplateVariant> &args);
-
-        FunctionDelegate() : m_objectPtr(0) , m_stubPtr(0) {}
-
-        /** Creates a delegate given an object. The method to call is passed as a template parameter */
-        template <class T, TemplateVariant (T::*TMethod)(const std::vector<TemplateVariant> &) const>
-        static FunctionDelegate fromMethod(const T* objectPtr)
-        {
-          FunctionDelegate d;
-          d.m_objectPtr = objectPtr;
-          d.m_stubPtr   = &methodStub<T, TMethod>;
-          return d;
-        }
-        /** Creates a delegate given an object, and a plain function. */
-        static FunctionDelegate fromFunction(const void *obj,StubType func)
-        {
-          FunctionDelegate d;
-          d.m_objectPtr = obj;
-          d.m_stubPtr = func;
-          return d;
-        }
-
-        /** Invokes the function/method stored in the delegate */
-        TemplateVariant operator()(const std::vector<TemplateVariant> &args) const
-        {
-          return (*m_stubPtr)(m_objectPtr, args);
-        }
-
-      private:
-        const void* m_objectPtr;
-        StubType    m_stubPtr;
-
-        template <class T, TemplateVariant (T::*TMethod)(const std::vector<TemplateVariant> &) const>
-        static TemplateVariant methodStub(const void* objectPtr, const std::vector<TemplateVariant> &args)
-        {
-          T* p = (T*)(objectPtr);
-          return (p->*TMethod)(args);
-        }
+      Bool       = 0,
+      Int        = 1,
+      String     = 2,
+      Struct     = 3,
+      List       = 4,
+      Function   = 5,
+      WeakStruct = 6,
+      None       = 255
     };
 
     /** Constructs an invalid variant. */
     TemplateVariant() {}
 
     /** Constructs a new variant with a boolean value \a b. */
-    explicit TemplateVariant(bool b) { m_variant.set<bool>(b); }
+    explicit TemplateVariant(bool b) { m_variant.set<static_cast<uint8_t>(Type::Bool)>(b); }
 
     /** Constructs a new variant with a integer value \a v. */
-    TemplateVariant(int v) { m_variant.set<int>(v); }
+    TemplateVariant(int v) { m_variant.set<static_cast<uint8_t>(Type::Int)>(v); }
 
     /** Constructs a new variant with a string value \a s. */
-    TemplateVariant(const char *s,bool raw=FALSE) : m_raw(raw) { m_variant.set<QCString>(s); }
+    TemplateVariant(const char *s,bool raw=FALSE) : m_raw(raw) { m_variant.set<static_cast<uint8_t>(Type::String)>(s); }
 
     /** Constructs a new variant with a string value \a s. */
-    TemplateVariant(const QCString &s,bool raw=FALSE) : m_raw(raw) { m_variant.set<QCString>(s); }
+    TemplateVariant(const QCString &s,bool raw=FALSE) : m_raw(raw) { m_variant.set<static_cast<uint8_t>(Type::String)>(s.str()); }
 
     /** Constructs a new variant with a string value \a s. */
-    TemplateVariant(const std::string &s,bool raw=FALSE) : m_raw(raw) { m_variant.set<QCString>(s); }
+    TemplateVariant(const std::string &s,bool raw=FALSE) : m_raw(raw) { m_variant.set<static_cast<uint8_t>(Type::String)>(s); }
 
     /** Constructs a new variant with a struct value \a s.
-     *  @note. The variant will hold a reference to the object.
+     *  @note. The variant will hold a counting reference to the object.
      */
-    TemplateVariant(TemplateStructIntf *s);
+    TemplateVariant(TemplateStructIntfPtr s) { m_variant.set<static_cast<uint8_t>(Type::Struct)>(s); }
 
     /** Constructs a new variant with a list value \a l.
-     *  @note. The variant will hold a reference to the object.
+     *  @note. The variant will hold a counting reference to the object.
      */
-    TemplateVariant(TemplateListIntf *l);
+    TemplateVariant(TemplateListIntfPtr l) { m_variant.set<static_cast<uint8_t>(Type::List)>(l); }
+
+    /** Constructs a new variant with a struct value \a s.
+     *  @note. The variant will hold a non-counting reference to the object.
+     */
+    TemplateVariant(TemplateStructIntfWeakPtr s) { m_variant.set<static_cast<uint8_t>(Type::WeakStruct)>(s); }
 
     /** Constructs a new variant which represents a method call
      *  @param[in] delegate FunctionDelegate object to invoke when
@@ -172,15 +163,15 @@ class TemplateVariant
      *  TemplateVariant::FunctionDelegate::fromFunction() to create
      *  FunctionDelegate objects.
      */
-    TemplateVariant(const FunctionDelegate &delegate) { m_variant.set<FunctionDelegate>(delegate); }
+    TemplateVariant(FunctionDelegate delegate) { m_variant.set<static_cast<uint8_t>(Type::Function)>(delegate); }
 
     /** Destroys the Variant object */
-    ~TemplateVariant();
+    ~TemplateVariant()  = default;
 
     /** Constructs a copy of the variant, \a v,
      *  passed as the argument to this constructor.
      */
-    TemplateVariant(const TemplateVariant &v);
+    TemplateVariant(const TemplateVariant &v) = default;
 
     /** Moves the contents of variant \a v into this variant.
      *  variant \a v will become invalid
@@ -188,7 +179,7 @@ class TemplateVariant
     TemplateVariant(TemplateVariant &&v);
 
     /** Assigns the value of the variant \a v to this variant. */
-    TemplateVariant &operator=(const TemplateVariant &v);
+    TemplateVariant &operator=(const TemplateVariant &v) = default;
 
     /** Move the value of the variant \a v into this variant.
      *  Variant \a v will become invalid */
@@ -197,33 +188,7 @@ class TemplateVariant
     /** Compares this QVariant with v and returns true if they are equal;
      *  otherwise returns false.
      */
-    bool operator==(TemplateVariant &other)
-    {
-      if (!m_variant.valid())
-      {
-        return FALSE;
-      }
-      if (isBool() && other.isBool())
-      {
-        return m_variant.get<bool>() == other.m_variant.get<bool>();
-      }
-      else if (isInt() && other.isInt())
-      {
-        return m_variant.get<int>() == other.m_variant.get<int>();
-      }
-      else if (isList() && other.isList())
-      {
-        return m_variant.get<TemplateListIntf*>() == other.m_variant.get<TemplateListIntf*>();
-      }
-      else if (isStruct() && other.isStruct())
-      {
-        return m_variant.get<TemplateStructIntf*>() == other.m_variant.get<TemplateStructIntf*>();
-      }
-      return toString()==other.toString();
-    }
-
-    QCString listToString() const;
-    QCString structToString() const;
+    bool operator==(TemplateVariant &other) const;
 
     /** Returns the variant as a string. */
     QCString toString() const;
@@ -235,51 +200,38 @@ class TemplateVariant
     int toInt() const;
 
     /** Returns TRUE if the variant holds a valid value, or FALSE otherwise */
-    constexpr bool isValid()    const { return m_variant.valid(); }
+    constexpr bool isValid()      const { return m_variant.valid(); }
     /** Returns TRUE if the variant holds a boolean value */
-    constexpr bool isBool()     const { return m_variant.is<bool>(); }
+    constexpr bool isBool()       const { return m_variant.is<static_cast<uint8_t>(Type::Bool)>(); }
     /** Returns TRUE if the variant holds an integer value */
-    constexpr bool isInt()      const { return m_variant.is<int>(); }
+    constexpr bool isInt()        const { return m_variant.is<static_cast<uint8_t>(Type::Int)>(); }
     /** Returns TRUE if the variant holds a string value */
-    constexpr bool isString()   const { return m_variant.is<QCString>(); }
+    constexpr bool isString()     const { return m_variant.is<static_cast<uint8_t>(Type::String)>(); }
     /** Returns TRUE if the variant holds a struct value */
-    constexpr bool isStruct()   const { return m_variant.is<TemplateStructIntf*>(); }
+    constexpr bool isStruct()     const { return m_variant.is<static_cast<uint8_t>(Type::Struct)>(); }
     /** Returns TRUE if the variant holds a list value */
-    constexpr bool isList()     const { return m_variant.is<TemplateListIntf*>(); }
+    constexpr bool isList()       const { return m_variant.is<static_cast<uint8_t>(Type::List)>(); }
     /** Returns TRUE if the variant holds a function value */
-    constexpr bool isFunction() const { return m_variant.is<FunctionDelegate>(); }
+    constexpr bool isFunction()   const { return m_variant.is<static_cast<uint8_t>(Type::Function)>(); }
+    /** Returns TRUE if the variant holds a struct value */
+    constexpr bool isWeakStruct() const { return m_variant.is<static_cast<uint8_t>(Type::WeakStruct)>(); }
 
     /** Returns the pointer to list referenced by this variant
      *  or 0 if this variant does not have list type.
      */
-    TemplateListIntf   *toList()
-    {
-      return isList() ? m_variant.get<TemplateListIntf*>() : nullptr;
-    }
-    const TemplateListIntf *toList() const
-    {
-      return isList() ? m_variant.get<TemplateListIntf*>() : nullptr;
-    }
+    TemplateListIntfPtr toList();
+    const TemplateListIntfPtr toList() const;
 
     /** Returns the pointer to struct referenced by this variant
      *  or 0 if this variant does not have struct type.
      */
-    TemplateStructIntf *toStruct()
-    {
-      return isStruct() ? m_variant.get<TemplateStructIntf*>() : nullptr;
-    }
-    const TemplateStructIntf *toStruct() const
-    {
-      return isStruct() ? m_variant.get<TemplateStructIntf*>() : nullptr;
-    }
+    TemplateStructIntfPtr toStruct();
+    const TemplateStructIntfPtr toStruct() const;
 
     /** Return the result of apply this function with \a args.
      *  Returns an empty string if the variant type is not a function.
      */
-    TemplateVariant call(const std::vector<TemplateVariant> &args)
-    {
-      return isFunction() ? m_variant.get<FunctionDelegate>()(args) : TemplateVariant();
-    }
+    TemplateVariant call(const std::vector<TemplateVariant> &args = std::vector<TemplateVariant>());
 
     /** Sets whether or not the value of the Variant should be
      *  escaped or written as-is (raw).
@@ -292,69 +244,21 @@ class TemplateVariant
      */
     constexpr bool raw() const { return m_raw; }
 
-    /** Symbolic names for the possible types that this variant can hold. */
-    enum class Type : size_t
-    {
-      None     = std::string::npos,
-      Bool     = 0,
-      Int      = 1,
-      String   = 2,
-      Struct   = 3,
-      List     = 4,
-      Function = 5
-    };
-
     /** Returns the type held by this variant */
     constexpr Type type() const { return static_cast<Type>(m_variant.index()); }
 
-    /** Return a string representation of the type of the value stored in the variant */
-    constexpr const char *typeAsString() const
-    {
-      switch (type())
-      {
-        case Type::None:       return "invalid";
-        case Type::Bool:       return "bool";
-        case Type::Int:        return "integer";
-        case Type::String:     return "string";
-        case Type::Struct:     return "struct";
-        case Type::List:       return "list";
-        case Type::Function:   return "function";
-      }
-      return "invalid";
-    }
+    /** Returns a string representation of this variant's type */
+    const char *typeAsString() const;
 
   private:
-    using VariantT = Variant<bool,                  // index==0: Type::Bool
-                             int,                   // index==1: Type::Int
-                             QCString,              // index==2: Type::String
-                             TemplateStructIntf*,   // index==3: Type::Struct
-                             TemplateListIntf*,     // index==4: Type::List
-                             FunctionDelegate       // index==5: Type::Function
-                            >;
+    QCString listToString() const;
+    QCString structToString() const;
+
     VariantT              m_variant;
     bool                  m_raw = false;
 };
 
-//------------------------------------------------------------------------
-
-template<class T> class TemplateAutoRef
-{
-  public:
-    TemplateAutoRef(T *obj) : m_obj(obj)
-    {
-      m_obj->addRef();
-    }
-   ~TemplateAutoRef()
-    {
-      m_obj->release();
-    }
-    T &operator*() const { return *m_obj; }
-    T *operator->() const { return m_obj; }
-    T *get() const { return m_obj; }
-
-  private:
-   T *m_obj;
-};
+using TemplateVariantList = std::vector<TemplateVariant>;
 
 //------------------------------------------------------------------------
 
@@ -385,6 +289,7 @@ class TemplateListIntf
          */
         virtual bool current(TemplateVariant &v) const = 0;
     };
+    using ConstIteratorPtr = std::unique_ptr<ConstIterator>;
 
     /** Destroys the list */
     virtual ~TemplateListIntf() {}
@@ -398,41 +303,32 @@ class TemplateListIntf
     /** Creates a new iterator for this list.
      *  @note the user should call delete on the returned pointer.
      */
-    virtual TemplateListIntf::ConstIterator *createIterator() const = 0;
-
-    /** Increase object's reference count */
-    virtual int addRef() = 0;
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const = 0;
 
-    /** Decreases object's reference count, destroy object if 0 */
-    virtual int release() = 0;
 };
 
-/** @brief Default implementation of a context value of type list. */
-class TemplateList : public TemplateListIntf
+/** @brief Default implementation of a immutable context value of type list. */
+class TemplateImmutableList : public TemplateListIntf
 {
   public:
     // TemplateListIntf methods
     virtual uint count() const;
     virtual TemplateVariant at(uint index) const;
-    virtual TemplateListIntf::ConstIterator *createIterator() const;
-    virtual int addRef();
-    virtual int release();
-
-    /** Creates an instance with ref count set to 0 */
-    static TemplateList *alloc();
+    virtual TemplateListIntf::ConstIteratorPtr createIterator() const;
 
-    /** Appends element \a v to the end of the list */
-    virtual void append(const TemplateVariant &v);
+    /** Creates an instance and returns a shared pointer to it */
+    static TemplateListIntfPtr alloc(std::initializer_list<TemplateVariant> elements);
+    static TemplateListIntfPtr alloc(const std::vector<TemplateVariant> &elements);
 
-  private:
     /** Creates a list */
-    TemplateList();
+    TemplateImmutableList(std::initializer_list<TemplateVariant> elements);
+    TemplateImmutableList(const std::vector<TemplateVariant> &elements);
     /** Destroys the list */
-   ~TemplateList();
+    virtual ~TemplateImmutableList();
 
-    friend class TemplateListConstIterator;
+  private:
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 //------------------------------------------------------------------------
@@ -451,45 +347,37 @@ class TemplateStructIntf
 
     /** Return the list of fields. */
     virtual StringVector fields() const = 0;
-
-    /** Increase object's reference count */
-    virtual int addRef() = 0;
-
-    /** Decreases object's reference count, destroy object if 0 */
-    virtual int release() = 0;
 };
 
+//------------------------------------------------------------------------
 
-/** @brief Default implementation of a context value of type struct. */
-class TemplateStruct : public TemplateStructIntf
+/** @brief Default implementation of an immutable context value of type struct. */
+class TemplateImmutableStruct : public TemplateStructIntf
 {
   public:
     // TemplateStructIntf methods
     virtual TemplateVariant get(const QCString &name) const;
     virtual StringVector fields() const;
-    virtual int addRef();
-    virtual int release();
 
-    /** Creates an instance with ref count set to 0. */
-    static TemplateStruct *alloc();
+    using StructField = std::pair<const std::string,TemplateVariant>;
 
-    /** Sets the value the field of a struct
-     *  @param[in] name The name of the field.
-     *  @param[in] v The value to set.
+    /** Creates an instance and returns a shared pointer to it
+     *  @param fields the fields of the struct as key/value pairs.
      */
-    virtual void set(const QCString &name,const TemplateVariant &v);
-
+    static TemplateStructIntfPtr alloc(std::initializer_list<StructField> fields);
 
-  private:
     /** Creates a struct */
-    TemplateStruct();
+    TemplateImmutableStruct(std::initializer_list<StructField> fields);
     /** Destroys the struct */
-    virtual ~TemplateStruct();
+    virtual ~TemplateImmutableStruct();
+
+  private:
 
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
+
 //------------------------------------------------------------------------
 
 /** @brief Interface used to escape characters in a string */
@@ -497,6 +385,8 @@ class TemplateEscapeIntf
 {
   public:
     virtual ~TemplateEscapeIntf() {}
+    /** Create a copy of the escape filter */
+    virtual std::unique_ptr<TemplateEscapeIntf> clone() = 0;
     /** Returns the \a input after escaping certain characters */
     virtual QCString escape(const QCString &input) = 0;
     /** Setting tabbing mode on or off (for LaTeX) */
@@ -510,6 +400,8 @@ class TemplateSpacelessIntf
 {
   public:
     virtual ~TemplateSpacelessIntf() {}
+    /** Create a copy of the spaceless filter */
+    virtual std::unique_ptr<TemplateSpacelessIntf> clone() = 0;
     /** Returns the \a input after removing redundant whitespace */
     virtual QCString remove(const QCString &input) = 0;
     /** Reset filter state */
@@ -567,12 +459,12 @@ class TemplateContext
     /** Sets the interface that will be used for escaping the result
      *  of variable expansion before writing it to the output.
      */
-    virtual void setEscapeIntf(const QCString &extension, TemplateEscapeIntf *intf) = 0;
+    virtual void setEscapeIntf(const QCString &extension, std::unique_ptr<TemplateEscapeIntf> intf) = 0;
 
     /** Sets the interface that will be used inside a spaceless block
      *  to remove any redundant whitespace.
      */
-    virtual void setSpacelessIntf(TemplateSpacelessIntf *intf) = 0;
+    virtual void setSpacelessIntf(std::unique_ptr<TemplateSpacelessIntf> intf) = 0;
 };
 
 //------------------------------------------------------------------------
@@ -609,12 +501,7 @@ class TemplateEngine
     /** Creates a new context that can be using to render a template.
      *  @see Template::render()
      */
-    TemplateContext *createContext() const;
-
-    /** Destroys a context created via createContext().
-     *  @param[in] ctx The context.
-     */
-    void destroyContext(TemplateContext *ctx);
+    std::unique_ptr<TemplateContext> createContext() const;
 
     /** Creates a new template whose contents are in a file.
      *  @param[in] fileName The name of the file containing the template data
@@ -650,7 +537,7 @@ class TemplateEngine
     QCString outputExtension() const;
 
     class Private;
-    Private *p;
+    std::unique_ptr<Private> p;
 };
 
 /** @} */
index a9c4a31..38027ec 100644 (file)
@@ -67,11 +67,13 @@ class TextStream final
     {
       flush();
       m_s = s;
+      m_f = nullptr;
     }
 
     void setFile(FILE *f)
     {
       flush();
+      m_s = nullptr;
       m_f = f;
     }
 
@@ -233,7 +235,7 @@ class TextStream final
       {
        n = (uint32_t)(-(int32_t)n);
       }
-      do { *--p = ((int32_t)(n%10)) + '0'; n /= 10; } while ( n );
+      do { *--p = ((char)(n%10)) + '0'; n /= 10; } while ( n );
       if ( neg ) *--p = '-';
       m_buffer+=p;
     }
index 38cda2c..d077ed6 100644 (file)
@@ -62,7 +62,18 @@ void TooltipManager::addTooltip(CodeOutputInterface &ol,const Definition *d)
   {
     id = id.right(id.length()-i-1); // strip path (for CREATE_SUBDIRS=YES)
   }
-  id+=escapeId(Doxygen::htmlFileExtension);
+  // In case an extension is present translate this extension to something understood by the tooltip handler
+  // otherwise extend t with a translated htmlFileExtension.
+  QCString currentExtension = getFileNameExtension(id);
+  if (currentExtension.isEmpty())
+  {
+    id += escapeId(Doxygen::htmlFileExtension);
+  }
+  else
+  {
+    id = stripExtensionGeneral(id,currentExtension) + escapeId(currentExtension);
+  }
+
   QCString anc = d->anchor();
   if (!anc.isEmpty())
   {
index baa4710..6a86fad 100644 (file)
@@ -19,6 +19,8 @@
  *    Thanks to Jorge Ramos, Fernando Carijo and others for their contributions.
  *
  * History:
+ * 20211003:
+ *  - Updated to 1.9.3;
  * 20200112:
  *     - Updated to 1.9.1;
  * 20190203:
@@ -52,7 +54,7 @@
 #ifndef TRANSLATOR_BR_H
 #define TRANSLATOR_BR_H
 
-class TranslatorBrazilian : public TranslatorAdapter_1_9_2
+class TranslatorBrazilian : public Translator
 {
   public:
 
@@ -808,6 +810,7 @@ class TranslatorBrazilian : public TranslatorAdapter_1_9_2
         bool single)
     { // here s is one of " Class", " Struct" or " Union"
       // single is true implies a single file
+      static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
       QCString result=(QCString)"A documentação para ";
       if (compType == ClassDef::Protocol)
       {
@@ -819,7 +822,7 @@ class TranslatorBrazilian : public TranslatorAdapter_1_9_2
       }
       switch(compType)
       {
-        case ClassDef::Class:      result+="classe "; break;
+        case ClassDef::Class:      result+=vhdlOpt?"Unidade de Design ":"classe "; break;
         case ClassDef::Struct:     result+="estrutura "; break;
         case ClassDef::Union:      result+="união "; break;
         case ClassDef::Interface:  result+="interface "; break;
@@ -2348,6 +2351,52 @@ class TranslatorBrazilian : public TranslatorAdapter_1_9_2
            return "Documentação da Unidade de Projeto";
     }
 
+
+       //////////////////////////////////////////////////////////////////////////
+       // new since 1.9.2
+       //////////////////////////////////////////////////////////////////////////
+
+       /** C++20 concept */
+       virtual QCString trConcept(bool first_capital, bool singular)
+       {
+         QCString result((first_capital ? "Conceito" : "conceito"));
+         if (!singular) result+="s";
+         return result;
+       }
+       /*! used as the title of the HTML page of a C++20 concept page */
+       virtual QCString trConceptReference(const QCString &conceptName)
+       {
+         QCString result= "Referência do Conceito ";
+         result+=conceptName;
+         return result;
+       }
+
+       /*! used as the title of page containing all the index of all concepts. */
+       virtual QCString trConceptList()
+       { return "Lista de Conceitos"; }
+
+       /*! used as the title of chapter containing the index listing all concepts. */
+       virtual QCString trConceptIndex()
+       { return "Índice de Conceitos"; }
+
+       /*! used as the title of chapter containing all information about concepts. */
+       virtual QCString trConceptDocumentation()
+       { return "Documentação do Conceito"; }
+
+       /*! used as an introduction to the concept list */
+       virtual QCString trConceptListDescription(bool extractAll)
+       {
+         QCString result="Esta é a lista de todos os conceitos ";
+         if (!extractAll) result+="documentados ";
+         result+="com suas respectivas descrições:";
+         return result;
+       }
+
+       /*! used to introduce the definition of the C++20 concept */
+       virtual QCString trConceptDefinition()
+       {
+         return "Definição de conceito";
+       }
 };
 
 #endif
index 8d3aa5e..2cc47e4 100644 (file)
@@ -24,7 +24,7 @@
 */
 #define CN_SPC " "
 
-class TranslatorChinese : public TranslatorAdapter_1_8_15
+class TranslatorChinese : public Translator
 {
   public:
     /*! Used for identification of the language. The identification
@@ -65,7 +65,7 @@ class TranslatorChinese : public TranslatorAdapter_1_8_15
     }
     virtual QCString latexDocumentPre()
     {
-      return "\\begin{CJK}{UTF8}{min}\n";
+      return "\\begin{CJK}{UTF8}{gbsn}\n";
     }
     virtual QCString latexDocumentPost()
     {
@@ -1916,6 +1916,281 @@ class TranslatorChinese : public TranslatorAdapter_1_8_15
       return "该单例的文档由下列文件生成:";
     }
 
+//////////////////////////////////////////////////////////////////////////
+// new since 1.8.15
+//////////////////////////////////////////////////////////////////////////
+
+    /** VHDL design unit hierarchy */
+    virtual QCString trDesignUnitHierarchy()
+    { return "设计单元层次结构"; }
+    /** VHDL design unit list */
+    virtual QCString trDesignUnitList()
+    { return "设计单元列表"; }
+    /** VHDL design unit members */
+    virtual QCString trDesignUnitMembers()
+    { return "设计单元成员"; }
+    /** VHDL design unit list description */
+    virtual QCString trDesignUnitListDescription()
+    {
+        return "这是所有设计单元成员的列表,以及指向他们所属实体的链接:";
+    }
+    /** VHDL design unit index */
+    virtual QCString trDesignUnitIndex()
+    { return "设计单元索引"; }
+    /** VHDL design units */
+    virtual QCString trDesignUnits()
+    { return "设计单元"; }
+    /** VHDL functions/procedures/processes */
+    virtual QCString trFunctionAndProc()
+    { return "函数/调用过程/进程语句"; }
+    /** VHDL type */
+    virtual QCString trVhdlType(uint64 type,bool single)
+    {
+      switch(type)
+      {
+        case VhdlDocGen::LIBRARY:
+          return "库";
+        case VhdlDocGen::PACKAGE:
+          return "包";
+        case VhdlDocGen::SIGNAL:
+          return "信号";
+        case VhdlDocGen::COMPONENT:
+          return "元件";
+        case VhdlDocGen::CONSTANT:
+          return "常量";
+        case VhdlDocGen::ENTITY:
+          return "实体";
+        case VhdlDocGen::TYPE:
+          return "类型";
+        case VhdlDocGen::SUBTYPE:
+          return "子类型";
+        case VhdlDocGen::FUNCTION:
+          return "函数";
+        case VhdlDocGen::RECORD:
+          return "记录";
+        case VhdlDocGen::PROCEDURE:
+          return "过程";
+        case VhdlDocGen::ARCHITECTURE:
+          return "结构体";
+        case VhdlDocGen::ATTRIBUTE:
+          return "属性";
+        case VhdlDocGen::PROCESS:
+          return "进程语句";
+        case VhdlDocGen::PORT:
+          return "端口";
+        case VhdlDocGen::USE:
+          if (single) return "使用语句";
+          else        return "使用语句";
+        case VhdlDocGen::GENERIC:
+          return "类属";
+        case VhdlDocGen::PACKAGE_BODY:
+          return "包体";
+        case VhdlDocGen::UNITS:
+          return "单元";
+        case VhdlDocGen::SHAREDVARIABLE:
+          return "共享变量";
+        case VhdlDocGen::VFILE:
+          return "文件";
+        case VhdlDocGen::GROUP:
+          return "组";
+        case VhdlDocGen::INSTANTIATION:
+          return "实例化";
+        case VhdlDocGen::ALIAS:
+          return "别名";
+        case VhdlDocGen::CONFIG:
+          return " 配置";
+        case VhdlDocGen::MISCELLANEOUS:
+          return "混合运算";
+        case VhdlDocGen::UCF_CONST:
+          return "约束";
+        default:
+          return "类";
+      }
+    }
+    virtual QCString trCustomReference(const QCString &name)
+    { return QCString(name)+" 引用"; }
+
+    /* Slice */
+    virtual QCString trConstants()
+    {
+        return "常量";
+    }
+    virtual QCString trConstantDocumentation()
+    {
+        return "常量文档";
+    }
+    virtual QCString trSequences()
+    {
+        return "序列";
+    }
+    virtual QCString trSequenceDocumentation()
+    {
+        return "序列文档";
+    }
+    virtual QCString trDictionaries()
+    {
+        return "字典";
+    }
+    virtual QCString trDictionaryDocumentation()
+    {
+        return "字典文档";
+    }
+    virtual QCString trSliceInterfaces()
+    {
+        return "接口";
+    }
+    virtual QCString trInterfaceIndex()
+    {
+        return "接口索引";
+    }
+    virtual QCString trInterfaceList()
+    {
+        return "接口列表";
+    }
+    virtual QCString trInterfaceListDescription()
+    {
+        return "以下是带有简要说明的接口:";
+    }
+    virtual QCString trInterfaceHierarchy()
+    {
+        return "接口层次结构";
+    }
+    virtual QCString trInterfaceHierarchyDescription()
+    {
+        return "此继承列表按字母顺序粗略排序:";
+    }
+    virtual QCString trInterfaceDocumentation()
+    {
+        return "接口文档";
+    }
+    virtual QCString trStructs()
+    {
+        return "结构";
+    }
+    virtual QCString trStructIndex()
+    {
+        return "结构索引";
+    }
+    virtual QCString trStructList()
+    {
+        return "结构列表";
+    }
+    virtual QCString trStructListDescription()
+    {
+        return "以下是带有简要说明的结构:";
+    }
+    virtual QCString trStructDocumentation()
+    {
+        return "结构文档";
+    }
+    virtual QCString trExceptionIndex()
+    {
+        return "异常索引";
+    }
+    virtual QCString trExceptionList()
+    {
+        return "异常列表";
+    }
+    virtual QCString trExceptionListDescription()
+    {
+        return "以下是带有简要说明的异常:";
+    }
+    virtual QCString trExceptionHierarchy()
+    {
+        return "异常层次结构";
+    }
+    virtual QCString trExceptionHierarchyDescription()
+    {
+        return "此继承列表按字母顺序粗略排序:";
+    }
+    virtual QCString trExceptionDocumentation()
+    {
+        return "异常文档";
+    }
+    virtual QCString trCompoundReferenceSlice(const QCString &clName, ClassDef::CompoundType compType, bool isLocal)
+    {
+      QCString result=(QCString)clName;
+      if (isLocal) result+=" 局部";
+      switch(compType)
+      {
+        case ClassDef::Class:      result+=" 类"; break;
+        case ClassDef::Struct:     result+=" 结构"; break;
+        case ClassDef::Union:      result+=" 联合"; break;
+        case ClassDef::Interface:  result+=" 接口"; break;
+        case ClassDef::Protocol:   result+=" 协议"; break;
+        case ClassDef::Category:   result+=" 类别"; break;
+        case ClassDef::Exception:  result+=" 异常"; break;
+        default: break;
+      }
+      result+=" 引用";
+      return result;
+    }
+    virtual QCString trOperations()
+    {
+        return "操作";
+    }
+    virtual QCString trOperationDocumentation()
+    {
+        return "操作文档";
+    }
+    virtual QCString trDataMembers()
+    {
+        return "数据成员";
+    }
+    virtual QCString trDataMemberDocumentation()
+    {
+        return "数据成员文档";
+    }
+
+//////////////////////////////////////////////////////////////////////////
+// new since 1.8.19
+//////////////////////////////////////////////////////////////////////////
+
+    /** VHDL design unit documentation */
+    virtual QCString trDesignUnitDocumentation()
+    { return "设计单元文档"; }
+
+//////////////////////////////////////////////////////////////////////////
+// new since 1.9.2
+//////////////////////////////////////////////////////////////////////////
+
+    /** C++20 concept */
+    virtual QCString trConcept(bool first_capital, bool singular)
+    {
+      return "概念";
+    }
+    /*! used as the title of the HTML page of a C++20 concept page */
+    virtual QCString trConceptReference(const QCString &conceptName)
+    {
+      QCString result=conceptName;
+      result+=" 概念引用";
+      return result;
+    }
+
+    /*! used as the title of page containing all the index of all concepts. */
+    virtual QCString trConceptList()
+    { return "概念列表"; }
+
+    /*! used as the title of chapter containing the index listing all concepts. */
+    virtual QCString trConceptIndex()
+    { return "概念索引"; }
+
+    /*! used as the title of chapter containing all information about concepts. */
+    virtual QCString trConceptDocumentation()
+    { return "概念文档"; }
+
+    /*! used as an introduction to the concept list */
+    virtual QCString trConceptListDescription(bool extractAll)
+    {
+      return "以下是带有简要说明的概念";
+    }
+
+    /*! used to introduce the definition of the C++20 concept */
+    virtual QCString trConceptDefinition()
+    {
+      return "概念定义";
+    }
+
 };
 
 #endif
index 1ce249e..ba38959 100644 (file)
@@ -20,6 +20,8 @@
 
 // Updates:
 // --------
+// 2021/08/31 - Updated for 1.9.3 version by: <petyovsky@feec.vutbr.cz>.
+// 2021/01/22 - Updated for 1.9.2 version by: <petyovsky@feec.vutbr.cz>.
 // 2013/04/11 - Updates for "new since 1.8.4".
 // 2012/07/31 - Updates for "new since 1.8.2".
 // 2012/04/10 - Updates for "new since 1.8.0".
@@ -85,7 +87,7 @@
 //    something else.  It is difficult to find the general translation
 //    for all kinds in the Czech language.
 
-class TranslatorCzech : public TranslatorAdapter_1_8_15
+class TranslatorCzech : public Translator
 {
   public:
     // --- Language control methods -------------------
@@ -173,7 +175,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
      *  parameter s is name of the project name.
      */
     virtual QCString trGeneratedAutomatically(const QCString &s)
-    { QCString result("Generováno automaticky programem Doxygen "
+    { QCString result("Vygenerováno automaticky programem Doxygen "
                       "ze zdrojových textů");
       if (!s.isEmpty()) result += QCString(" projektu ") + s;
       result += ".";
@@ -261,8 +263,16 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
 
     /*! This is an introduction to the class hierarchy. */
     virtual QCString trClassHierarchyDescription()
-    { return "Zde naleznete seznam, vyjadřující vztah dědičnosti tříd. "
-             "Je seřazen přibližně (ale ne úplně) podle abecedy:";
+    {
+      if (Config_getBool(OPTIMIZE_OUTPUT_VHDL))
+      {
+        return "Zde je hierarchický seznam všech entit:";
+      }
+      else
+      {
+        return "Zde naleznete seznam, vyjadřující vztah dědičnosti tříd. "
+               "Je seřazen přibližně (ale ne úplně) podle abecedy:";
+      }
     }
 
     /*! This is an introduction to the list with all files. */
@@ -277,11 +287,17 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     /*! This is an introduction to the annotated compound list. */
     virtual QCString trCompoundListDescription()
     {
+
       if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C))
       {
         return "Následující seznam obsahuje identifikace datových "
                       "struktur a jejich stručné popisy:";
       }
+      else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE))
+      {
+        return "Následující seznam obsahuje identifikace tříd. "
+                      "V seznamu jsou uvedeny jejich stručné popisy:";
+      }
       else
       {
         return "Následující seznam obsahuje především identifikace "
@@ -300,7 +316,6 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
       {
         result += "dokumentovaných ";
       }
-
       if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C))
       {
         result += "položek struktur (struct) a unií (union) ";
@@ -309,32 +324,29 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
       {
         result += "členů tříd ";
       }
-
       result += "s odkazy na ";
-
-      if (extractAll)
+      if (!extractAll)
       {
         if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C))
         {
-          result += "dokumentaci struktur/unií, ke kterým příslušejí:";
+          result+="struktury/unie, ke kterým příslušejí:";
         }
         else
         {
-          result += "dokumentaci tříd, ke kterým příslušejí:";
+          result+="třídy, ke kterým příslušejí:";
         }
       }
       else
       {
         if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C))
         {
-          result+="struktury/unie, ke kterým příslušejí:";
+          result += "dokumentaci struktur/unií, ke kterým příslušejí:";
         }
         else
         {
-          result+="třídy, ke kterým příslušejí:";
+          result += "dokumentaci tříd, ke kterým příslušejí:";
         }
       }
-
       return result;
     }
 
@@ -359,7 +371,6 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
         result+="soubory, ke kterým příslušejí:";
       else
         result+="dokumentaci:";
-
       return result;
     }
 
@@ -377,7 +388,6 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
 
     // index titles (the project name is prepended for these)
 
-
     /*! This is used in HTML as the title of index.html. */
     virtual QCString trDocumentation()
     { return "Dokumentace"; }
@@ -430,6 +440,10 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
       {
         return "Dokumentace datových struktur";
       }
+      else if (Config_getBool(OPTIMIZE_OUTPUT_VHDL))
+      {
+          return trDesignUnitDocumentation();
+      }
       else
       {
         return "Dokumentace tříd";
@@ -531,7 +545,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     {
       if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C))
       {
-        return "Datové struktry";
+        return "Datové struktury";
       }
       else
       {
@@ -544,17 +558,16 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
      */
     virtual QCString trGeneratedAt(const QCString &date,const QCString &projName)
     {
-      QCString result("Generováno ");
-      result += date;
-      if (!projName.isEmpty()) result += QCString(" pro projekt ") + projName;
-      result += " programem";
+      QCString result=(QCString)"Vygenerováno dne: "+date;
+      if (!projName.isEmpty()) result += QCString(", pro projekt: ") + projName;
+      result+=(QCString)", programem";
       return result;
     }
 
     /*! this text is put before a class diagram */
     virtual QCString trClassDiagram(const QCString &clName)
     {
-      return QCString("Diagram dědičnosti pro třídu ") + clName;
+      return QCString("Diagram dědičnosti pro třídu ") + clName+":";
     }
 
     /*! this text is generated when the \\internal command is used. */
@@ -591,20 +604,22 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
 
     /*! this text is used in the title page of a LaTeX document. */
     virtual QCString trGeneratedBy()
-    { return "Generováno programem"; }
+    { return "Vygenerováno programem"; }
 
-    // new since 0.49-990307
+//////////////////////////////////////////////////////////////////////////
+// new since 0.49-990307
+//////////////////////////////////////////////////////////////////////////
 
     /*! used as the title of page containing all the index of all namespaces. */
     virtual QCString trNamespaceList()
-    { return "Seznam prostorů jmen"; }
+    { return "Seznam jmenných prostorů"; }
 
     /*! used as an introduction to the namespace list */
     virtual QCString trNamespaceListDescription(bool extractAll)
     {
       QCString result="Zde naleznete seznam všech ";
       if (!extractAll) result+="dokumentovaných ";
-      result+="prostorů jmen se stručným popisem:";
+      result+="jmenných prostorů se stručným popisem:";
       return result;
     }
 
@@ -612,7 +627,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
      *  friends of a class
      */
     virtual QCString trFriends()
-    { return "Friends"; }
+    { return "Přátelé třídy"; }
 
 //////////////////////////////////////////////////////////////////////////
 // new since 0.49-990405
@@ -622,7 +637,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
      * related classes
      */
     virtual QCString trRelatedFunctionDocumentation()
-    { return "Dokumentace k friends"; }
+    { return "Dokumentace přátel a souvisejících funkcí třídy"; }
 
 //////////////////////////////////////////////////////////////////////////
 // new since 0.49-990425
@@ -661,7 +676,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     /*! used as the title of the HTML page of a namespace */
     virtual QCString trNamespaceReference(const QCString &namespaceName)
     {
-      QCString result("Dokumentace prostoru jmen ");
+      QCString result("Dokumentace jmenného prostoru ");
       result+=namespaceName;
       return result;
     }
@@ -752,39 +767,37 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
      */
     virtual QCString trReimplementedInList(int numEntries)
     {
-      QCString result("Reimplementováno v ");
-      result += trWriteList(numEntries) + ".";
-      return result;
+      return "Reimplementováno v "+trWriteList(numEntries)+".";
     }
 
     /*! This is put above each page as a link to all members of namespaces. */
     virtual QCString trNamespaceMembers()
-    { return "Symboly v prostorech jmen"; }
+    { return "Symboly ve jmenném prostoru"; }
 
     /*! This is an introduction to the page with all namespace members */
     virtual QCString trNamespaceMemberDescription(bool extractAll)
     {
       QCString result="Zde naleznete seznam všech ";
       if (!extractAll) result+="dokumentovaných ";
-      result+="symbolů, které jsou definovány ve svých prostorech jmen. "
+      result+="symbolů, které jsou definovány ve svých jmenných prostorech. "
               "U každého je uveden odkaz na ";
       if (extractAll)
-        result+="dokumentaci příslušného prostoru jmen:";
+        result+="dokumentaci příslušného jmenného prostoru:";
       else
-        result+="příslušný prostor jmen:";
+        result+="příslušný jmenný prostor:";
       return result;
     }
     /*! This is used in LaTeX as the title of the chapter with the
      *  index of all namespaces.
      */
     virtual QCString trNamespaceIndex()
-    { return "Rejstřík prostorů jmen"; }
+    { return "Rejstřík jmenných prostorů"; }
 
     /*! This is used in LaTeX as the title of the chapter containing
      *  the documentation of all namespaces.
      */
     virtual QCString trNamespaceDocumentation()
-    { return "Dokumentace prostorů jmen"; }
+    { return "Dokumentace jmenných prostorů"; }
 
 //////////////////////////////////////////////////////////////////////////
 // new since 0.49-990522
@@ -794,7 +807,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
      *  namespaces in a file.
      */
     virtual QCString trNamespaces()
-    { return "Prostory jmen"; }
+    { return "Jmenné prostory"; }
 
 //////////////////////////////////////////////////////////////////////////
 // new since 0.49-990728
@@ -805,21 +818,20 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
      */
     virtual QCString trGeneratedFromFiles(ClassDef::CompoundType compType,
         bool single)
-    { // here s is one of " Class", " Struct" or " Union"
-      // single is true implies a single file
+    { // single is true implies a single file
       QCString result=(QCString)"Dokumentace pro ";
       switch(compType)
       {
         case ClassDef::Class:      result+="tuto třídu"; break;
-        case ClassDef::Struct:     result+="tuto strukturu (struct)"; break;
-        case ClassDef::Union:      result+="tuto unii (union)"; break;
+        case ClassDef::Struct:     result+="tuto strukturu"; break;
+        case ClassDef::Union:      result+="tuto unii"; break;
         case ClassDef::Interface:  result+="toto rozhraní"; break;
-        case ClassDef::Protocol:   result+="tento protokol "; break;
-        case ClassDef::Category:   result+="tuto kategorii "; break;
+        case ClassDef::Protocol:   result+="tento protokol"; break;
+        case ClassDef::Category:   result+="tuto kategorii"; break;
         case ClassDef::Exception:  result+="tuto výjimku"; break;
         default: break;
       }
-      result+=" byla generována z ";
+      result+=" byla vygenerována z ";
       if (single) result+="následujícího souboru:";
       else        result+="následujících souborů:";
       return result;
@@ -873,13 +885,12 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     /*! this text is put before a collaboration diagram */
     virtual QCString trCollaborationDiagram(const QCString &clName)
     {
-      return (QCString)"Diagram tříd pro "+clName+":";
+      return (QCString)"Diagram pro "+clName+":";
     }
     /*! this text is put before an include dependency graph */
     virtual QCString trInclDepGraph(const QCString &fName)
     {
-      return (QCString)"Graf závislostí na vkládaných souborech "
-                    "pro "+fName+":";
+      return (QCString)"Graf závislostí na vkládaných souborech pro "+fName+":";
     }
     /*! header that is put before the list of constructor/destructors. */
     virtual QCString trConstructorDocumentation()
@@ -914,7 +925,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     /*! Text shown before a multi-line variable/enum initialization */
     virtual QCString trInitialValue()
     {
-      return "Initializer:";
+      return "Inicializační hodnota:";
     }
     /*! Text used the source code in the file index */
     virtual QCString trCode()
@@ -994,7 +1005,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
 // new since 1.1.3
 //////////////////////////////////////////////////////////////////////////
 
-    /*! Used as a marker that is put before a todo item */
+    /*! Used as a marker that is put before a \\todo item */
     virtual QCString trTodo()
     {
       return "Plánované úpravy";
@@ -1031,7 +1042,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
       return "Od"; // ??? not checked in a context
     }
 
-////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
 // new since 1.1.5
 //////////////////////////////////////////////////////////////////////////
 
@@ -1045,7 +1056,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     {
       return
         "Zde naleznete vysvětlení, jak mají být interpretovány grafy, "
-        "které byly generovány programem doxygen.<p>\n"
+        "které byly vygenerovány programem doxygen.<p>\n"
         "Uvažujte následující příklad:\n"
         "\\code\n"
         "/*! Neviditelná třída, která se v grafu nezobrazuje, protože "
@@ -1080,39 +1091,42 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
         "};\n"
         "\\endcode\n"
         "K výše uvedenému bude vygenerován následující graf:"
-        "<p><center><img src=\"graph_legend."+getDotImageExtension()+"\"></center>\n"
+        "<p><center><img alt=\"\" src=\"graph_legend."+getDotImageExtension()+"\"></center></p>\n"
         "<p>\n"
         "Bloky (tj. uzly) v uvedeném grafu mají následující význam:\n"
+        "</p>\n"
         "<ul>\n"
         "<li>Šedě vyplněný obdélník reprezentuje strukturu nebo třídu, "
-            "pro kterou byl graf generován.\n"
+            "pro kterou byl graf vygenerován.</li>\n"
         "<li>Obdélník s černým obrysem označuje dokumentovanou "
-            "strukturu nebo třídu.\n"
+            "strukturu nebo třídu.</li>\n"
         "<li>Obdélník s šedým obrysem označuje nedokumentovanou "
-            "strukturu nebo třídu.\n"
+            "strukturu nebo třídu.</li>\n"
         "<li>Obdélník s červeným obrysem označuje dokumentovanou "
             "strukturu nebo třídu, pro kterou\n"
             "nejsou zobrazeny všechny vztahy dědičnosti nebo obsažení. "
             "Graf je ořezán v případě, kdy jej\n"
-            "není možné umístit do vymezeného prostoru.\n"
+            "není možné umístit do vymezeného prostoru.</li>\n"
         "</ul>\n"
+        "<p>\n"
         "Šipky (tj. hrany grafu) mají následující význam:\n"
+        "</p>\n"
         "<ul>\n"
         "<li>Tmavě modrá šipka se používá pro označení vztahu veřejné "
-            "dědičnosti (public) mezi dvěma třídami.\n"
+            "dědičnosti (public) mezi dvěma třídami.</li>\n"
         "<li>Tmavě zelená šipka označuje vztah chráněné dědičnosti "
-            "(protected).\n"
+            "(protected).</li>\n"
         "<li>Tmavě červená šipka označuje vztah privátní dědičnosti "
-            "(private).\n"
+            "(private).</li>\n"
         "<li>Purpurová šipka kreslená čárkovaně se používá v případě, "
             "kdy je třída obsažena v jiné třídě,\n"
             "nebo kdy je používána jinou třídou. Je označena identifikátorem "
             "jedné nebo více proměných, přes které\n"
-            "je třída nebo struktura zpřístupněna.\n"
+            "je třída nebo struktura zpřístupněna.</li>\n"
         "<li>Žlutá šipka kreslená čárkovaně vyjadřuje vztah mezi instancí šablony "
             "a šablonou třídy, na základě které byla\n"
             "instance šablony vytvořena. V popisu šipky jsou uvedeny  příslušné"
-            " parametry šablony.\n"
+            " parametry šablony.</li>\n"
         "</ul>\n";
     }
     /*! text for the link to the legend page */
@@ -1130,7 +1144,6 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     {
       return "Test";
     }
-
     /*! Used as the header of the test list */
     virtual QCString trTestList()
     {
@@ -1158,7 +1171,14 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     /*! Used for Java classes in the summary section of Java packages */
     virtual QCString trClasses()
     {
-      return "Třídy";
+      if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C))
+      {
+        return "Datové struktury";
+      }
+      else
+      {
+        return "Třídy";
+      }
     }
     /*! Used as the title of a Java package */
     virtual QCString trPackage(const QCString &name)
@@ -1203,16 +1223,43 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     }
 
 //////////////////////////////////////////////////////////////////////////
-// new since 1.2.6-20010422
-//////////////////////////////////////////////////////////////////////////
-
-    /*! Used as ansicpg for RTF file */
+// new since 1.2.6
+//////////////////////////////////////////////////////////////////////////
+
+    /*! Used as ansicpg for RTF file
+     *
+     * The following table shows the correlation of Charset name, Charset Value and
+     * <pre>
+     * Codepage number:
+     * Charset Name       Charset Value(hex)  Codepage number
+     * ------------------------------------------------------
+     * DEFAULT_CHARSET           1 (x01)
+     * SYMBOL_CHARSET            2 (x02)
+     * OEM_CHARSET             255 (xFF)
+     * ANSI_CHARSET              0 (x00)            1252
+     * RUSSIAN_CHARSET         204 (xCC)            1251
+     * EE_CHARSET              238 (xEE)            1250
+     * GREEK_CHARSET           161 (xA1)            1253
+     * TURKISH_CHARSET         162 (xA2)            1254
+     * BALTIC_CHARSET          186 (xBA)            1257
+     * HEBREW_CHARSET          177 (xB1)            1255
+     * ARABIC _CHARSET         178 (xB2)            1256
+     * SHIFTJIS_CHARSET        128 (x80)             932
+     * HANGEUL_CHARSET         129 (x81)             949
+     * GB2313_CHARSET          134 (x86)             936
+     * CHINESEBIG5_CHARSET     136 (x88)             950
+     * </pre>
+     *
+     */
     virtual QCString trRTFansicp()
     {
       return "1250";
     }
 
-    /*! Used as ansicpg for RTF fcharset */
+
+    /*! Used as ansicpg for RTF fcharset
+     *  \see trRTFansicp() for a table of possible values.
+     */
     virtual QCString trRTFCharSet()
     {
       return "238";
@@ -1252,9 +1299,10 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
      */
     virtual QCString trNamespace(bool first_capital, bool singular)
     {
-      QCString result((first_capital ? "Prostor" : "prostor"));
+      QCString result((first_capital ? "Jmenn" : "jmenn"));
+      result += singular ? "ý" : "é";
+      result+=" prostor";
       if (!singular)  result+="y";
-      result+=" jmen";
       return result;
     }
 
@@ -1287,14 +1335,17 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     virtual QCString trMember(bool first_capital, bool singular)
     {
       QCString result((first_capital ? "Člen" : "člen"));
-      if (!singular)
-          result += "y";
+      if (!singular)  result += "y";
       return result;
     }
 
     /*! ??? Jak to prelozit? Bylo by dobre, kdyby se ozval nekdo,
      * kdo to pouziva.
      */
+    /*! This is used for translation of the word that will possibly
+     *  be followed by a single name or by a list of names
+     *  of the category.
+     */
     virtual QCString trGlobal(bool first_capital, bool singular)
     {
       QCString result((first_capital ? "Global" : "global"));
@@ -1470,7 +1521,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
       }
       else if (numDocuments==1)
       {
-        return "Nalezen jediný dokument, který vyhovuje vašemu dotazu.";
+        return "Nalezen jeden dokument, který vyhovuje vašemu dotazu.";
       }
       else
       {
@@ -1498,12 +1549,10 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
       return QCString("Zdrojový soubor ") + filename;
     }
 
-
 //////////////////////////////////////////////////////////////////////////
 // new since 1.3.9
 //////////////////////////////////////////////////////////////////////////
 
-
     /*! This is used as the name of the chapter containing the directory
      *  hierarchy.
      */
@@ -1517,7 +1566,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     { return "Dokumentace k adresářům"; }
 
     /*! This is used as the title of the directory index and also in the
-     *  Quick links of a HTML page, to link to the directory hierarchy.
+     *  Quick links of an HTML page, to link to the directory hierarchy.
      */
     virtual QCString trDirectories()
     { return "Adresáře"; }
@@ -1542,14 +1591,14 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     }
 
     /*! This returns the word directory with or without starting capital
-     *  (\a first_capital) and in sigular or plural form (\a singular).
+     *  (\a first_capital) and in singular or plural form (\a singular).
      */
     virtual QCString trDir(bool first_capital, bool singular)
     {
-        QCString result((first_capital ? "Adresář" : "adresář"));
-        if ( ! singular)
-            result += "e";
-        return result;
+      QCString result((first_capital ? "Adresář" : "adresář"));
+      if (!singular)
+        result += "e";
+      return result;
     }
 
 //////////////////////////////////////////////////////////////////////////
@@ -1570,19 +1619,17 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
 // new since 1.4.6
 //////////////////////////////////////////////////////////////////////////
 
+    /*! This is used to introduce a caller (or called-by) graph */
     virtual QCString trCallerGraph()
     {
       return "Tuto funkci volají...";
     }
 
-
     /*! This is used in the documentation of a file/namespace before the list
      *  of documentation blocks for enumeration values
      */
     virtual QCString trEnumerationValueDocumentation()
-    {
-      return "Dokumentace výčtových hodnot";
-    }
+    { return "Dokumentace výčtových hodnot"; }
 
 //////////////////////////////////////////////////////////////////////////
 // new since 1.5.4 (mainly for Fortran)
@@ -1607,7 +1654,6 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     /*! This is an introduction to the page with all data types (Fortran). */
     virtual QCString trCompoundMembersDescriptionFortran(bool extractAll)
     {
-
       QCString result="Následuje seznam všech ";
       if (!extractAll)
       {
@@ -1736,12 +1782,13 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
       if (!singular)  result+="y";
       return result;
     }
+
     /*! This is put at the bottom of a module documentation page and is
      *  followed by a list of files that were used to generate the page.
      */
     virtual QCString trGeneratedFromFilesFortran(ClassDef::CompoundType compType,
         bool single)
-    { // here s is one of " Module", " Struct" or " Union"
+    {
       // single is true implies a single file
       QCString result=(QCString)"Dokumentace ";
       switch(compType)
@@ -1760,6 +1807,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
       else result+="následujících souborů:";
       return result;
     }
+
     /*! This is used for translation of the word that will possibly
      *  be followed by a single name or by a list of names
      *  of the category.
@@ -1770,6 +1818,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
       if (!singular)  result+="y";
       return result;
     }
+
     /*! This is used for translation of the word that will possibly
      *  be followed by a single name or by a list of names
      *  of the category.
@@ -1781,7 +1830,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
       return result;
     }
 
-    /*! C# Type Contraint list */
+    /*! C# Type Constraint list */
     virtual QCString trTypeConstraints()
     {
       return "Omezení typů (Type Constraints)";
@@ -1806,7 +1855,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     /*! Label used for search results in the global namespace */
     virtual QCString trGlobalNamespace()
     {
-      return "Globální prostor jmen";
+      return "Globální jmenný prostor";
     }
 
     /*! Message shown while searching */
@@ -1884,7 +1933,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
 
     /*! Header for the graph showing the directory dependencies */
     virtual QCString trDirDepGraph(const QCString &name)
-    { return QCString("Graf závislosti na adresářích pro  ")+name+":"; }
+    { return QCString("Graf závislosti na adresářích pro ")+name+":"; }
 
 //////////////////////////////////////////////////////////////////////////
 // new since 1.8.0
@@ -1904,7 +1953,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
 
     /*! Used file list for a Java enum */
     virtual QCString trEnumGeneratedFromFiles(bool single)
-    { QCString result = "Dokumentace pro tento výčet byla generována z ";
+    { QCString result = "Dokumentace pro tento výčet byla vygenerována z ";
       if (single)
           result += "následujícího souboru:";
       else
@@ -2022,7 +2071,7 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     virtual QCString trServiceGeneratedFromFiles(bool single)
     {
       // single is true implies a single file
-      QCString result="Dokumentace k této službě byla generována ";
+      QCString result="Dokumentace k této službě byla vygenerována ";
       if (single) result+="z následujícího souboru:";
       else        result+="z následujících souborů:";
       return result;
@@ -2031,12 +2080,317 @@ class TranslatorCzech : public TranslatorAdapter_1_8_15
     virtual QCString trSingletonGeneratedFromFiles(bool single)
     {
       // single is true implies a single file
-      QCString result="Dokumentace k tomuto singletonu byla generována ";
+      QCString result="Dokumentace k tomuto singletonu byla vygenerována ";
       if (single) result+="z následujícího souboru:";
       else        result+="z následujících souborů:";
       return result;
     }
 
+//////////////////////////////////////////////////////////////////////////
+// new since 1.8.15
+//////////////////////////////////////////////////////////////////////////
+
+    /** VHDL design unit hierarchy */
+    virtual QCString trDesignUnitHierarchy()
+    { return "Hierarchie návrhových jednotek"; }
+    /** VHDL design unit list */
+    virtual QCString trDesignUnitList()
+    { return "Seznam návrhových jednotek"; }
+    /** VHDL design unit members */
+    virtual QCString trDesignUnitMembers()
+    { return "Seznam členů návrhových jednotky"; }
+    /** VHDL design unit list description */
+    virtual QCString trDesignUnitListDescription()
+    {
+        return "Zde naleznete seznam všech členů návrhové jednotky s odkazy na "
+            "entity, ke kterým příslušejí:";
+    }
+    /** VHDL design unit index */
+    virtual QCString trDesignUnitIndex()
+    { return "Rejstřík návrhových jednotek"; }
+    /** VHDL design units */
+    virtual QCString trDesignUnits()
+    { return "Návrhové jednotky"; }
+    /** VHDL functions/procedures/processes */
+    virtual QCString trFunctionAndProc()
+    { return "Funkce/Procedury/Procesy"; }
+    /** VHDL type */
+    virtual QCString trVhdlType(uint64 type,bool single)
+    {
+      switch(type)
+      {
+        case VhdlDocGen::LIBRARY:
+          if (single) return "Knihovna";
+          else        return "Knihovny";
+        case VhdlDocGen::PACKAGE:
+          if (single) return "Balík";
+          else        return "Balíky";
+        case VhdlDocGen::SIGNAL:
+          if (single) return "Signál";
+          else        return "Signály";
+        case VhdlDocGen::COMPONENT:
+          if (single) return "Komponenta";
+          else        return "Komponenty";
+        case VhdlDocGen::CONSTANT:
+          if (single) return "Konstanta";
+          else        return "Konstanty";
+        case VhdlDocGen::ENTITY:
+          if (single) return "Entita";
+          else        return "Entity";
+        case VhdlDocGen::TYPE:
+          if (single) return "Typ";
+          else        return "Typy";
+        case VhdlDocGen::SUBTYPE:
+          if (single) return "Subtyp";
+          else        return "Subtypy";
+        case VhdlDocGen::FUNCTION:
+          if (single) return "Funkce";
+          else        return "Funkce";
+        case VhdlDocGen::RECORD:
+          if (single) return "Záznam";
+          else        return "Záznamy";
+        case VhdlDocGen::PROCEDURE:
+          if (single) return "Procedura";
+          else        return "Procedury";
+        case VhdlDocGen::ARCHITECTURE:
+          if (single) return "Architektura";
+          else        return "Architektury";
+        case VhdlDocGen::ATTRIBUTE:
+          if (single) return "Atribut";
+          else        return "Atributy";
+        case VhdlDocGen::PROCESS:
+          if (single) return "Proces";
+          else        return "Procesy";
+        case VhdlDocGen::PORT:
+          if (single) return "Brána";
+          else        return "Brány";
+        case VhdlDocGen::USE:
+          if (single) return "Klauzule use";
+          else        return "Klauzule use";
+        case VhdlDocGen::GENERIC:
+          if (single) return "Generický parametr";
+          else        return "Generické parametry";
+        case VhdlDocGen::PACKAGE_BODY:
+          return "Tělo balíku";
+        case VhdlDocGen::UNITS:
+          return "Fyzikální jednotky";
+        case VhdlDocGen::SHAREDVARIABLE:
+          if (single) return "Sdílená proměnná";
+          else        return "Sdílené proměnné";
+        case VhdlDocGen::VFILE:
+          if (single) return "Soubor";
+          else        return "Soubory";
+        case VhdlDocGen::GROUP:
+          if (single) return "Skupina";
+          else        return "Skupiny";
+        case VhdlDocGen::INSTANTIATION:
+          if (single) return "Vložená instance";
+          else        return "Vložené instance";
+        case VhdlDocGen::ALIAS:
+          if (single) return "Alias";
+          else        return "Aliasy";
+        case VhdlDocGen::CONFIG:
+          if (single) return "Konfigurace";
+          else        return "Konfigurace";
+        case VhdlDocGen::MISCELLANEOUS:
+          return "Ostatní";
+        case VhdlDocGen::UCF_CONST:
+          return "Omezení (constraints)";
+        default:
+          return "Třída";
+      }
+    }
+    virtual QCString trCustomReference(const QCString &name)
+    { return "Dokumentace pro "+QCString(name); }
+
+    /* Slice */
+    virtual QCString trConstants()
+    {
+        return "Konstanty";
+    }
+    virtual QCString trConstantDocumentation()
+    {
+        return "Dokumentace konstant";
+    }
+    virtual QCString trSequences()
+    {
+        return "Sekvence";
+    }
+    virtual QCString trSequenceDocumentation()
+    {
+        return "Dokumentace sekvence";
+    }
+    virtual QCString trDictionaries()
+    {
+        return "Slovníky";
+    }
+    virtual QCString trDictionaryDocumentation()
+    {
+        return "Dokumentace slovníku";
+    }
+    virtual QCString trSliceInterfaces()
+    {
+        return "Rozhraní";
+    }
+    virtual QCString trInterfaceIndex()
+    {
+        return "Rejstřík rozhraní";
+    }
+    virtual QCString trInterfaceList()
+    {
+        return "Seznam rozhraní";
+    }
+    virtual QCString trInterfaceListDescription()
+    {
+        return "Následující seznam obsahuje jména rozhraní a jejich stručné popisy:";
+    }
+    virtual QCString trInterfaceHierarchy()
+    {
+        return "Hierarchie rozhraní";
+    }
+    virtual QCString trInterfaceHierarchyDescription()
+    {
+        return "Zde naleznete seznam, vyjadřující vztah dědičnosti rozhraní. Je seřazen přibližně (ale ne úplně) podle abecedy:";
+    }
+    virtual QCString trInterfaceDocumentation()
+    {
+        return "Dokumentace rozhraní";
+    }
+    virtual QCString trStructs()
+    {
+        return "Struktury";
+    }
+    virtual QCString trStructIndex()
+    {
+        return "Rejstřík struktur";
+    }
+    virtual QCString trStructList()
+    {
+        return "Seznam struktur";
+    }
+    virtual QCString trStructListDescription()
+    {
+        return "Následující seznam obsahuje jména struktur a jejich stručné popisy:";
+    }
+    virtual QCString trStructDocumentation()
+    {
+        return "Dokumentace struktur";
+    }
+    virtual QCString trExceptionIndex()
+    {
+        return "Rejstřík vyjímek";
+    }
+    virtual QCString trExceptionList()
+    {
+        return "Seznam vyjímek";
+    }
+    virtual QCString trExceptionListDescription()
+    {
+        return "Následující seznam obsahuje jména výjímek a jejich stručné popisy:";
+    }
+    virtual QCString trExceptionHierarchy()
+    {
+        return "Hierarchie vyjímek";
+    }
+    virtual QCString trExceptionHierarchyDescription()
+    {
+        return "Zde naleznete seznam, vyjadřující vztah dědičnosti vyjímek. Je seřazen přibližně (ale ne úplně) podle abecedy:";
+    }
+    virtual QCString trExceptionDocumentation()
+    {
+        return "Dokumentace vyjímek";
+    }
+    virtual QCString trCompoundReferenceSlice(const QCString &clName, ClassDef::CompoundType compType, bool isLocal)
+    {
+      QCString result("Dokumentace ");
+      if (isLocal) result+=" lokální";
+      switch(compType)
+      {
+        case ClassDef::Class:      result+=" třídy "; break;
+        case ClassDef::Struct:     result+=" struktury "; break;
+        case ClassDef::Union:      result+=" unie "; break;
+        case ClassDef::Interface:  result+=" rozhraní "; break;
+        case ClassDef::Protocol:
+           if (isLocal) result+="ho";
+           result+=" protokolu ";
+        break;
+        case ClassDef::Category:   result+=" kategorie "; break;
+        case ClassDef::Exception:  result+=" vyjímky "; break;
+        default: break;
+      }
+      result += clName;
+      return result;
+    }
+    virtual QCString trOperations()
+    {
+        return "Operace";
+    }
+    virtual QCString trOperationDocumentation()
+    {
+        return "Dokumentace operace";
+    }
+    virtual QCString trDataMembers()
+    {
+        return "Datové členy";
+    }
+    virtual QCString trDataMemberDocumentation()
+    {
+        return "Dokumentace datových členů";
+    }
+
+//////////////////////////////////////////////////////////////////////////
+// new since 1.8.19
+//////////////////////////////////////////////////////////////////////////
+
+    /** VHDL design unit documentation */
+    virtual QCString trDesignUnitDocumentation()
+    { return "Dokumentace návrhové jednotky"; }
+
+//////////////////////////////////////////////////////////////////////////
+// new since 1.9.2
+//////////////////////////////////////////////////////////////////////////
+
+    /** C++20 concept */
+    virtual QCString trConcept(bool first_capital, bool singular)
+    {
+      QCString result((first_capital ? "Koncept" : "koncept"));
+      if (!singular) result+="y";
+      return result;
+    }
+    /*! used as the title of the HTML page of a C++20 concept page */
+    virtual QCString trConceptReference(const QCString &conceptName)
+    {
+      QCString result("Dokumentace konceptu ");
+      result+=conceptName;
+      return result;
+    }
+
+    /*! used as the title of page containing all the index of all concepts. */
+    virtual QCString trConceptList()
+    { return "Seznam konceptů"; }
+
+    /*! used as the title of chapter containing the index listing all concepts. */
+    virtual QCString trConceptIndex()
+    { return "Rejstřík konceptů"; }
+
+    /*! used as the title of chapter containing all information about concepts. */
+    virtual QCString trConceptDocumentation()
+    { return "Dokumentace konceptů"; }
+
+    /*! used as an introduction to the concept list */
+    virtual QCString trConceptListDescription(bool extractAll)
+    {
+      QCString result="Následuje seznam všech ";
+      if (!extractAll) result+="dokumentovaných ";
+      result+="konceptů se stručnými popisy:";
+      return result;
+    }
+
+    /*! used to introduce the definition of the C++20 concept */
+    virtual QCString trConceptDefinition()
+    {
+      return "Definice konceptů";
+    }
 };
 
 #endif // TRANSLATOR_CZ_H
index ff7b704..d7d2de9 100644 (file)
@@ -864,10 +864,11 @@ class TranslatorGerman : public TranslatorAdapter_1_8_15
     virtual QCString trGeneratedFromFiles(ClassDef::CompoundType compType,
         bool single)
     { // single is true implies a single file
+      static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
       QCString result=(QCString)"Die Dokumentation für diese";
       switch(compType)
       {
-        case ClassDef::Class:      result+=Klasse"; break;
+        case ClassDef::Class:      result+=vhdlOpt?"Entwurfseinheiten":"Klasse"; break;
         case ClassDef::Struct:     result+=" Struktur"; break;
         case ClassDef::Union:      result+=" Variante"; break;
         case ClassDef::Interface:  result+=" Schnittstelle"; break;
index 3e456cc..55d6742 100644 (file)
@@ -766,10 +766,11 @@ class TranslatorEnglish : public Translator
     virtual QCString trGeneratedFromFiles(ClassDef::CompoundType compType,
         bool single)
     { // single is true implies a single file
+      static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
       QCString result=(QCString)"The documentation for this ";
       switch(compType)
       {
-        case ClassDef::Class:      result+="class"; break;
+        case ClassDef::Class:      result+=vhdlOpt?"design unit":"class"; break;
         case ClassDef::Struct:     result+="struct"; break;
         case ClassDef::Union:      result+="union"; break;
         case ClassDef::Interface:  result+="interface"; break;
index 41dbd8f..dff426c 100644 (file)
@@ -756,10 +756,11 @@ class TranslatorSpanish : public TranslatorAdapter_1_8_15
         bool single)
     { // here s is one of " Class", " Struct" or " Union"
       // single is true implies a single file
+      static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
       QCString result=(QCString)"La documentación para est";
       switch(compType)
       {
-        case ClassDef::Class:      result+="a clase"; break;
+        case ClassDef::Class:      result+=vhdlOpt? "a unidades de diseño":"a clase"; break;
         case ClassDef::Struct:     result+="a estructura"; break;
         case ClassDef::Union:      result+="a unión"; break;
         case ClassDef::Interface:  result+="e interfaz"; break;
index 9bbcf2c..a612760 100644 (file)
@@ -822,11 +822,12 @@ class TranslatorFrench : public TranslatorAdapter_1_8_15
         bool single)
     { // here s is one of " Class", " Struct" or " Union"
       // single is true implies a single file
+      static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
       bool feminine = true;
       QCString result=(QCString)"La documentation de ";
       switch(compType)
       {
-        case ClassDef::Class:      result+="cette classe"; break;
+        case ClassDef::Class:      result+=vhdlOpt? "cette unités de conception":"cette classe"; break;
         case ClassDef::Struct:     result+="cette structure"; break;
         case ClassDef::Union:      result+="cette union"; break;
         case ClassDef::Interface:  result+="cette interface"; break;
index b40b2ec..41d39f1 100644 (file)
  * 01 Jan 2009 : Greek maintenance by
  *               Paul Gessos <gessos.paul@gmail.com>
  *
- * Last update : 06 Jan 2015
+ *
+ * Δουλεύω με C, C++, Java, PHP και Python. Άλλες γλώσσες (π.χ. VHDL) μου είναι
+ * άγνωστες.
+ * Αν παρατηρήσετε σφάλματα ΠΑΡΑΚΑΛΩ ΠΟΛΥ επικοινωνήστε μαζί μου.
  */
 
 /*     English to Greek keyword dictionary
        exception -> εξαίρεση
        namespace -> χώρος ονομάτων
        enumeration -> απαρίθμηση
+       concept -> έννοια
+       signal -> σήμα
+       instantiation -> ενσάρκωση
 */
 
 
 #ifndef TRANSLATOR_GR_H
 #define TRANSLATOR_GR_H
 
-class TranslatorGreek : public TranslatorAdapter_1_8_15
+class TranslatorGreek : public Translator
 {
   public:
 
@@ -1878,7 +1884,7 @@ class TranslatorGreek : public TranslatorAdapter_1_8_15
 
     /*! Header of a Java enum page (Java enums are represented as classes). */
     virtual QCString trEnumReference(const QCString &name)
-    { return QCString("Αναφορά Απαρίθμησης ") + QCString(name); }
+    { return QCString("Αναφορά Απαρίθμησης ") + name; }
 
     /*! Used for a section containing inherited members */
     virtual QCString trInheritedFrom(const QCString &members,const QCString &what)
@@ -2001,7 +2007,308 @@ class TranslatorGreek : public TranslatorAdapter_1_8_15
       return result;
     }
 
+//////////////////////////////////////////////////////////////////////////
+// new since 1.8.15
+//////////////////////////////////////////////////////////////////////////
 
+    /** VHDL design unit hierarchy */
+    virtual QCString trDesignUnitHierarchy()
+    { return "Ιεραρχία Μονάδας Σχεδιασμού"; }
+    /** VHDL design unit list */
+    virtual QCString trDesignUnitList()
+    { return "Λίστα Μονάδας Σχεδιασμού"; }
+    /** VHDL design unit members */
+    virtual QCString trDesignUnitMembers()
+    { return "Μέλη Μονάδας Σχεδιασμού"; }
+    /** VHDL design unit list description */
+    virtual QCString trDesignUnitListDescription()
+    {
+        return "Ακολουθεί μια λίστα από τα μέλη της μονάδας σχεδιασμού με συνδέσμους στις Οντότητες στις οποίες ανήκουν:";
+    }
+    /** VHDL design unit index */
+    virtual QCString trDesignUnitIndex()
+    { return "Ευρετήριο Μονάδων Σχεδιασμού"; }
+    /** VHDL design units */
+    virtual QCString trDesignUnits()
+    { return "Μονάδες Σχεδιασμού"; }
+    /** VHDL functions/procedures/processes */
+    virtual QCString trFunctionAndProc()
+    { return "Συναρτήσεις/Διαδικασίες/Διεργασίες"; }
+    /** VHDL type */
+    virtual QCString trVhdlType(uint64 type,bool single)
+    {
+      switch(type)
+      {
+        case VhdlDocGen::LIBRARY:
+          if (single) return "Βιβλιοθήκη";
+          else        return "Βιβλιοθήκες";
+        case VhdlDocGen::PACKAGE:
+          if (single) return "Πακέτο";
+          else        return "Πακέτα";
+        case VhdlDocGen::SIGNAL:
+          if (single) return "Σήμα";
+          else        return "Σήματα";
+        case VhdlDocGen::COMPONENT:
+          if (single) return "Εξάρτημα";
+          else        return "Εξαρτήματα";
+        case VhdlDocGen::CONSTANT:
+          if (single) return "Σταθερά";
+          else        return "Σταθερές";
+        case VhdlDocGen::ENTITY:
+          if (single) return "Οντότητα";
+          else        return "Οντότητες";
+        case VhdlDocGen::TYPE:
+          if (single) return "Τύπος";
+          else        return "Τύποι";
+        case VhdlDocGen::SUBTYPE:
+          if (single) return "Υποτύπος";
+          else        return "Υποτύποι";
+        case VhdlDocGen::FUNCTION:
+          if (single) return "Συνάρτηση";
+          else        return "Συναρτήσεις";
+        case VhdlDocGen::RECORD:
+          if (single) return "Εγγραφή";
+          else        return "Εγγραφές";
+        case VhdlDocGen::PROCEDURE:
+          if (single) return "Διαδικασία";
+          else        return "Διαδικασίες";
+        case VhdlDocGen::ARCHITECTURE:
+          if (single) return "Αρχιτεκτονική";
+          else        return "Αρχιτεκτονικές";
+        case VhdlDocGen::ATTRIBUTE:
+          if (single) return "Ιδιότητα";
+          else        return "Ιδιότητες";
+        case VhdlDocGen::PROCESS:
+          if (single) return "Διεργασία";
+          else        return "Διεργασίες";
+        case VhdlDocGen::PORT:
+          if (single) return "Πόρτα";
+          else        return "Πόρτες";
+        case VhdlDocGen::USE:
+          if (single) return "χρήση διάταξης";
+          else        return "Χρήση Διατάξεων";
+        case VhdlDocGen::GENERIC:
+          if (single) return "Γενίκευση";
+          else        return "Γενικεύσεις";
+        case VhdlDocGen::PACKAGE_BODY:
+          return "Σώμα Πακέτου";
+        case VhdlDocGen::UNITS:
+          return "Μονάδες";
+        case VhdlDocGen::SHAREDVARIABLE:
+          if (single) return "Κοινόχρηστη Μεταβλητή";
+          else        return "Κοινόχρηστες Μεταβλητές";
+        case VhdlDocGen::VFILE:
+          if (single) return "Αρχείο";
+          else        return "Αρχεία";
+        case VhdlDocGen::GROUP:
+          if (single) return "Ομάδα";
+          else        return "Ομάδες";
+        case VhdlDocGen::INSTANTIATION:
+          if (single) return "Ενσάρκωση";
+          else        return "Ενσαρκώσεις";
+        case VhdlDocGen::ALIAS:
+          if (single) return "Συνώνυμο";
+          else        return "Συνώνυμα";
+        case VhdlDocGen::CONFIG:
+          if (single) return "Ρύθμιση";
+          else        return "Ρυθμίσεις";
+        case VhdlDocGen::MISCELLANEOUS:
+          return "Διάφορα";
+        case VhdlDocGen::UCF_CONST:
+          return "Εξαναγκασμοί";
+        default:
+          return "Κλάση";
+      }
+    }
+    virtual QCString trCustomReference(const QCString &name)
+    { return QCString("Τεκμηρίωση ")+name; }
+
+    /* Slice */
+    virtual QCString trConstants()
+    {
+        return "Σταθερές";
+    }
+    virtual QCString trConstantDocumentation()
+    {
+        return "Τεκμηρίωση Σταθεράς";
+    }
+    virtual QCString trSequences()
+    {
+        return "Ακολουθίες";
+    }
+    virtual QCString trSequenceDocumentation()
+    {
+        return "Τεκμηρίωση Ακολουθίας";
+    }
+    virtual QCString trDictionaries()
+    {
+        return "Λεξικά";
+    }
+    virtual QCString trDictionaryDocumentation()
+    {
+        return "Τεκμηρίωση Λεξικού";
+    }
+    virtual QCString trSliceInterfaces()
+    {
+        return "Διεπαφές";
+    }
+    virtual QCString trInterfaceIndex()
+    {
+        return "Ευρετήριο Διεπαφής";
+    }
+    virtual QCString trInterfaceList()
+    {
+        return "Λίστα Διεπαφής";
+    }
+    virtual QCString trInterfaceListDescription()
+    {
+        return "Ακολουθούν οι διεπαφές με σύντομες περιγραφές:";
+    }
+    virtual QCString trInterfaceHierarchy()
+    {
+        return "Ιεραρχία Διεπαφής";
+    }
+    virtual QCString trInterfaceHierarchyDescription()
+    {
+        return "Αυτή η λίστα ιεραρχίας είναι ταξινομημένη χονδροειδώς και όχι αυστηρά αλφαβητικά:";
+    }
+    virtual QCString trInterfaceDocumentation()
+    {
+        return "Τεκμηρίωση Διεπαφής";
+    }
+    virtual QCString trStructs()
+    {
+        return "Δομές";
+    }
+    virtual QCString trStructIndex()
+    {
+        return "Ευρετήριο Δομής";
+    }
+    virtual QCString trStructList()
+    {
+        return "Λίστα Δομής";
+    }
+    virtual QCString trStructListDescription()
+    {
+        return "Ακολουθούν οι δομές με σύντομες περιγραφές:";
+    }
+    virtual QCString trStructDocumentation()
+    {
+        return "Τεκμηρίωση Δομής";
+    }
+    virtual QCString trExceptionIndex()
+    {
+        return "Ευρετήριο Εξαιρέσεων";
+    }
+    virtual QCString trExceptionList()
+    {
+        return "Λίστα Εξαίρεσης";
+    }
+    virtual QCString trExceptionListDescription()
+    {
+        return "Ακολουθούν οι εξαιρέσεις με σύντομες περιγραφές:";
+    }
+    virtual QCString trExceptionHierarchy()
+    {
+        return "Ιεραρχία Εξαίρεσης";
+    }
+    virtual QCString trExceptionHierarchyDescription()
+    {
+        return "Αυτή η λίστα ιεραρχίας είναι ταξινομημένη χονδροειδώς και όχι αυστηρά αλφαβητικά:";
+    }
+    virtual QCString trExceptionDocumentation()
+    {
+        return "Τεκμηρίωση Εξαίρεσης";
+    }
+    virtual QCString trCompoundReferenceSlice(const QCString &clName, ClassDef::CompoundType compType, bool isLocal)
+    {
+      QCString result="Τεκμηρίωση ";
+      if (isLocal)
+               result+=compType == ClassDef::Protocol ? "Τοπικού " : "Τοπικής ";
+      switch(compType)
+      {
+        case ClassDef::Class:      result+="Κλάσης "; break;
+        case ClassDef::Struct:     result+="Δομής "; break;
+        case ClassDef::Union:      result+="Ένωσης "; break;
+        case ClassDef::Interface:  result+="Διεπαφής "; break;
+        case ClassDef::Protocol:   result+="Πρωτοκόλλου "; break;
+        case ClassDef::Category:   result+="Κατηγορίας "; break;
+        case ClassDef::Exception:  result+="Εξαίρεσης "; break;
+        default: break;
+      }
+      result+=clName;
+      return result;
+    }
+    virtual QCString trOperations()
+    {
+        return "Πράξεις";
+    }
+    virtual QCString trOperationDocumentation()
+    {
+        return "Τεκμηρίωση Πράξης";
+    }
+    virtual QCString trDataMembers()
+    {
+        return "Μέλη Δεδομένων";
+    }
+    virtual QCString trDataMemberDocumentation()
+    {
+        return "Τεκμηρίωση Μέλους Δεδομένων";
+    }
+
+//////////////////////////////////////////////////////////////////////////
+// new since 1.8.19
+//////////////////////////////////////////////////////////////////////////
+
+    /** VHDL design unit documentation */
+    virtual QCString trDesignUnitDocumentation()
+    { return "Τεκμηρίωση Μονάδας Σχεδιασμού"; }
+
+//////////////////////////////////////////////////////////////////////////
+// new since 1.9.2
+//////////////////////////////////////////////////////////////////////////
+
+    /** C++20 concept */
+    virtual QCString trConcept(bool first_capital, bool singular)
+    {
+      QCString result((first_capital ? "Έννοι" : "έννοι"));
+      result+=singular ? "α" : "ες";
+      return result;
+    }
+    /*! used as the title of the HTML page of a C++20 concept page */
+    virtual QCString trConceptReference(const QCString &conceptName)
+    {
+      QCString result("Αναφορά Έννοιας ");
+      result+=conceptName;
+      return result;
+    }
+
+    /*! used as the title of page containing all the index of all concepts. */
+    virtual QCString trConceptList()
+    { return "Λίστα Έννοιας"; }
+
+    /*! used as the title of chapter containing the index listing all concepts. */
+    virtual QCString trConceptIndex()
+    { return "Ευρετήριο Έννοιας"; }
+
+    /*! used as the title of chapter containing all information about concepts. */
+    virtual QCString trConceptDocumentation()
+    { return "Τεκμηρίωση Έννοιας"; }
+
+    /*! used as an introduction to the concept list */
+    virtual QCString trConceptListDescription(bool extractAll)
+    {
+      QCString result="Ακολουθεί μια λίστα από όλες τις ";
+      if (!extractAll) result+="τεκμηριωμένες ";
+      result+="έννοιες με σύντομες περιγραφές:";
+      return result;
+    }
+
+    /*! used to introduce the definition of the C++20 concept */
+    virtual QCString trConceptDefinition()
+    {
+      return "Ορισμός Έννοιας";
+    }
 };
 
 #endif
index 7bf8db3..0e4171b 100644 (file)
@@ -414,10 +414,11 @@ class TranslatorDutch : public Translator
         bool single)
     { // here s is one of " Class", " Struct" or " Union"
       // single is true implies a single file
+      static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
       QCString result=(QCString)"De documentatie voor ";
       switch(compType)
       {
-        case ClassDef::Class:      result+="deze klasse"; break;
+        case ClassDef::Class:      result+=vhdlOpt?"deze ontwerp eenheid":"deze klasse"; break;
         case ClassDef::Struct:     result+="deze struct"; break;
         case ClassDef::Union:      result+="deze union"; break;
         case ClassDef::Interface:  result+="dit interface"; break;
index 223ca53..8bfbf96 100644 (file)
@@ -26,6 +26,8 @@
  * VERSION HISTORY
  * ---------------
  * History:
+ * 20211003:
+ *  - Updated to 1.9.3;
  * 20200112:
  *     - Updated to 1.9.1;
  * 20190203:
@@ -63,7 +65,7 @@
 #define TRANSLATOR_PT_H
 
 
-class TranslatorPortuguese : public TranslatorAdapter_1_9_2
+class TranslatorPortuguese : public Translator
 {
   public:
 
@@ -770,10 +772,11 @@ class TranslatorPortuguese : public TranslatorAdapter_1_9_2
         bool single)
     { // here s is one of " Class", " Struct" or " Union"
       // single is true implies a single file
+      static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
       QCString result=(QCString)"A documentação para ";
       switch(compType)
       {
-        case ClassDef::Class:      result+="esta classe"; break;
+        case ClassDef::Class:      result+=vhdlOpt?"esta Unidade de Design":"esta classe"; break;
         case ClassDef::Struct:     result+="esta estrutura"; break;
         case ClassDef::Union:      result+="esta união"; break;
         case ClassDef::Interface:  result+="este interface"; break;
@@ -2285,6 +2288,52 @@ class TranslatorPortuguese : public TranslatorAdapter_1_9_2
        {
            return "Documentação da Unidade de Projeto";
     }
+
+
+       //////////////////////////////////////////////////////////////////////////
+       // new since 1.9.2
+       //////////////////////////////////////////////////////////////////////////
+       /** C++20 concept */
+       virtual QCString trConcept(bool first_capital, bool singular)
+       {
+         QCString result((first_capital ? "Conceito" : "conceito"));
+         if (!singular) result+="s";
+         return result;
+       }
+       /*! used as the title of the HTML page of a C++20 concept page */
+       virtual QCString trConceptReference(const QCString &conceptName)
+       {
+         QCString result= "Referência do Conceito ";
+         result+=conceptName;
+         return result;
+       }
+
+       /*! used as the title of page containing all the index of all concepts. */
+       virtual QCString trConceptList()
+       { return "Lista de Conceitos"; }
+
+       /*! used as the title of chapter containing the index listing all concepts. */
+       virtual QCString trConceptIndex()
+       { return "Índice de Conceitos"; }
+
+       /*! used as the title of chapter containing all information about concepts. */
+       virtual QCString trConceptDocumentation()
+       { return "Documentação do Conceito"; }
+
+       /*! used as an introduction to the concept list */
+       virtual QCString trConceptListDescription(bool extractAll)
+       {
+         QCString result="Esta é a lista de todos os conceitos ";
+         if (!extractAll) result+="documentados ";
+         result+="com suas respectivas descrições:";
+         return result;
+       }
+
+       /*! used to introduce the definition of the C++20 concept */
+       virtual QCString trConceptDefinition()
+       {
+         return "Definição de conceito";
+       }
 };
 
 #endif
index 4916694..31f764f 100644 (file)
@@ -95,6 +95,11 @@ I left use clause untouched as I didn't find a suitable translation for it.
 English:
 * Updated the language translation to 1.8.19
 
+2020/08/19
+* Uppdaterat översättningarna till 1.9.2
+English:
+* Updated the language translation to 1.9.2
+
 ===================================================================================
   Ordlista
 ===================================================================================
@@ -151,7 +156,7 @@ English:
 #ifndef TRANSLATOR_SE_H
 #define TRANSLATOR_SE_H
 
-class TranslatorSwedish : public TranslatorAdapter_1_9_2
+class TranslatorSwedish : public Translator
 {
   public:
 
@@ -866,10 +871,11 @@ class TranslatorSwedish : public TranslatorAdapter_1_9_2
         bool single)
     { // here s is one of " Class", " Struct" or " Union"
       // single is true implies a single file
+      static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
       QCString result=(QCString)"Dokumentationen för ";
       switch(compType)
       {
-        case ClassDef::Class:      result+="denna klass"; break;
+        case ClassDef::Class:      result+=vhdlOpt? "denna designenhets":"denna klass"; break;
         case ClassDef::Struct:     result+="denna strukt"; break;
         case ClassDef::Union:      result+="denna union"; break;
         case ClassDef::Interface:  result+="detta gränssnitt"; break;
@@ -2354,5 +2360,49 @@ class TranslatorSwedish : public TranslatorAdapter_1_9_2
     virtual QCString trDesignUnitDocumentation()
     { return "Designenhetsdokumentation"; }
 
+//////////////////////////////////////////////////////////////////////////
+// new since 1.9.2
+//////////////////////////////////////////////////////////////////////////
+
+    /** C++20 concept */
+    virtual QCString trConcept(bool first_capital, bool singular)
+    {
+      QCString result((first_capital ? "Koncept" : "koncept"));
+      return result;
+    }
+    /*! used as the title of the HTML page of a C++20 concept page */
+    virtual QCString trConceptReference(const QCString &conceptName)
+    {
+      QCString result=conceptName;
+      result+=" Konceptreferens";
+      return result;
+    }
+
+    /*! used as the title of page containing all the index of all concepts. */
+    virtual QCString trConceptList()
+    { return "Konceptlista"; }
+
+    /*! used as the title of chapter containing the index listing all concepts. */
+    virtual QCString trConceptIndex()
+    { return "Konceptindex"; }
+
+    /*! used as the title of chapter containing all information about concepts. */
+    virtual QCString trConceptDocumentation()
+    { return "Konceptdokumentation"; }
+
+    /*! used as an introduction to the concept list */
+    virtual QCString trConceptListDescription(bool extractAll)
+    {
+      QCString result="Här är listan över alla ";
+      if (!extractAll) result+="dokumenterade ";
+      result+="koncept med en kort beskrivning:";
+      return result;
+    }
+
+    /*! used to introduce the definition of the C++20 concept */
+    virtual QCString trConceptDefinition()
+    {
+      return "Konceptdefinition";
+    }
 };
 #endif
index 2bb7056..69d8f7e 100644 (file)
@@ -104,6 +104,8 @@ enum MemberListType
   MemberListType_declarationLists   = 0x2000,
   MemberListType_documentationLists = 0x4000,
 
+  MemberListType_undefined               = -1,
+
   MemberListType_pubMethods              = 0,
   MemberListType_proMethods              = 1,
   MemberListType_pacMethods              = 2,
index cab6530..9d9cc41 100644 (file)
@@ -166,7 +166,7 @@ const int maxInheritanceDepth = 100000;
 QCString removeAnonymousScopes(const QCString &str)
 {
   std::string result;
-  if (str.isEmpty()) return result;
+  if (str.isEmpty()) return QCString(result);
 
   // helper to check if the found delimiter starts with a colon
   auto startsWithColon = [](const std::string &del)
@@ -227,7 +227,7 @@ QCString replaceAnonymousScopes(const QCString &s,const QCString &replacement)
   std::string result = reg::replace(s.str(),marker,
                                     replacement.isEmpty() ? replacement.data() : "__anonymous__");
   //printf("replaceAnonymousScopes('%s')='%s'\n",qPrint(s),qPrint(result));
-  return result;
+  return QCString(result);
 }
 
 
@@ -889,12 +889,12 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope,
     bool keepSpaces,int indentLevel)
 {
   if (text.isEmpty()) return;
-  //printf("linkify='%s'\n",text);
+  //printf("linkify='%s'\n",qPrint(text));
   std::string txtStr=text.str();
   size_t strLen = txtStr.length();
   if (strLen==0) return;
 
-  static const reg::Ex regExp(R"(\a[\w~!\\.:$]*)");
+  static const reg::Ex regExp(R"((::)?\a[\w~!\\.:$]*)");
   reg::Iterator it(txtStr,regExp);
   reg::Iterator end;
 
@@ -1204,14 +1204,6 @@ QCString tempArgListToString(const ArgumentList &al,SrcLangExt lang,bool include
       if (!first) result+=", ";
       if (!a.name.isEmpty()) // add template argument name
       {
-        if (a.type.left(4)=="out") // C# covariance
-        {
-          result+="out ";
-        }
-        else if (a.type.left(3)=="in") // C# contravariance
-        {
-          result+="in ";
-        }
         if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp)
         {
           result+=a.type+" ";
@@ -1412,7 +1404,7 @@ QCString fileToString(const QCString &name,bool filter,bool isSourceCode)
     {
       contents+=line+'\n';
     }
-    return contents;
+    return QCString(contents);
   }
   else // read from file
   {
@@ -4004,7 +3996,7 @@ QCString convertToXML(const QCString &s, bool keepEntities)
 }
 
 /*! Converts a string to an DocBook-encoded string */
-QCString convertToDocBook(const QCString &s)
+QCString convertToDocBook(const QCString &s, const bool retainNewline)
 {
   if (s.isEmpty()) return s;
   GrowBuf growBuf;
@@ -4016,6 +4008,7 @@ QCString convertToDocBook(const QCString &s)
   {
     switch (c)
     {
+      case '\n': if (retainNewline) growBuf.addStr("<literallayout>&#160;&#xa;</literallayout>"); growBuf.addChar(c);   break;
       case '<':  growBuf.addStr("&lt;");   break;
       case '>':  growBuf.addStr("&gt;");   break;
       case '&':  // possibility to have a special symbol
@@ -4407,13 +4400,13 @@ int extractClassNameFromType(const QCString &type,int &pos,QCString &name,QCStri
         pos=i+l;
       }
       //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=TRUE i=%d\n",
-      //    type,pos,qPrint(name),qPrint(templSpec),i);
+      //    qPrint(type),pos,qPrint(name),qPrint(templSpec),i);
       return i;
     }
   }
   pos = typeLen;
   //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=FALSE\n",
-  //       type,pos,qPrint(name),qPrint(templSpec));
+  //       qPrint(type),pos,qPrint(name),qPrint(templSpec));
   return -1;
 }
 
@@ -4428,7 +4421,7 @@ QCString normalizeNonTemplateArgumentsInString(
   p++;
   QCString result = name.left(p);
 
-  std::string s = result.mid(p).str();
+  std::string s = name.mid(p).str();
   static const reg::Ex re(R"([\a:][\w:]*)");
   reg::Iterator it(s,re);
   reg::Iterator end;
@@ -4488,7 +4481,7 @@ QCString substituteTemplateArgumentsInString(
     const std::unique_ptr<ArgumentList> &actualArgs)
 {
   //printf("substituteTemplateArgumentsInString(name=%s formal=%s actualArg=%s)\n",
-  //    qPrint(name),qPrint(argListToString(formalArgs)),qPrint(argListToString(actualArgs)));
+  //    qPrint(nm),qPrint(argListToString(formalArgs)),actualArgs ? qPrint(argListToString(*actualArgs)): "");
   if (formalArgs.empty()) return nm;
   QCString result;
 
@@ -4793,10 +4786,6 @@ PageDef *addRelatedPage(const QCString &name,const QCString &ptitle,
     pd->setRefItems(sli);
     newPage = false;
   }
-  else if (pd) // we are from a tag file
-  {
-    Doxygen::pageLinkedMap->del(name);
-  }
 
   if (newPage) // new page
   {
@@ -4807,9 +4796,21 @@ PageDef *addRelatedPage(const QCString &name,const QCString &ptitle,
       baseName=baseName.left(baseName.length()-Doxygen::htmlFileExtension.length());
 
     //printf("Appending page '%s'\n",qPrint(baseName));
-    pd = Doxygen::pageLinkedMap->add(baseName,
-        std::unique_ptr<PageDef>(
-           createPageDef(fileName,docLine,baseName,doc,title)));
+    if (pd) // replace existing page
+    {
+      pd->setDocumentation(doc,fileName,docLine);
+      pd->setFileName(::convertNameToFile(baseName,FALSE,TRUE));
+      pd->setShowLineNo(FALSE);
+      pd->setNestingLevel(0);
+      pd->setPageScope(0);
+      pd->setTitle(title);
+    }
+    else // newPage
+    {
+      pd = Doxygen::pageLinkedMap->add(baseName,
+          std::unique_ptr<PageDef>(
+             createPageDef(fileName,docLine,baseName,doc,title)));
+    }
     pd->setBodySegment(startLine,startLine,-1);
 
     pd->setRefItems(sli);
@@ -4932,7 +4933,7 @@ void addGroupListToTitle(OutputList &ol,const Definition *d)
 }
 
 void filterLatexString(TextStream &t,const QCString &str,
-    bool insideTabbing,bool insidePre,bool insideItem,bool insideTable,bool keepSpaces)
+    bool insideTabbing,bool insidePre,bool insideItem,bool insideTable,bool keepSpaces, const bool retainNewline)
 {
   if (str.isEmpty()) return;
   //if (strlen(str)<2) stackTrace();
@@ -4971,6 +4972,8 @@ void filterLatexString(TextStream &t,const QCString &str,
         case '-':  t << "-\\/"; break;
         case '^':  insideTable ? t << "\\string^" : t << (char)c;    break;
         case '~':  t << "\\string~";    break;
+        case '\n':  if (retainNewline) t << "\\newline"; else t << ' ';
+                   break;
         case ' ':  if (keepSpaces) t << "~"; else t << ' ';
                    break;
         default:
@@ -5058,6 +5061,8 @@ void filterLatexString(TextStream &t,const QCString &str,
                    break;
         case '\'': t << "\\textquotesingle{}";
                    break;
+        case '\n':  if (retainNewline) t << "\\newline"; else t << ' ';
+                   break;
         case ' ':  if (keepSpaces) { if (insideTabbing) t << "\\>"; else t << '~'; } else t << ' ';
                    break;
 
@@ -6269,7 +6274,7 @@ QCString filterTitle(const QCString &title)
     p=i+l;
   }
   tf+=t.substr(p);
-  return tf;
+  return QCString(tf);
 }
 
 //----------------------------------------------------------------------------
@@ -6430,7 +6435,7 @@ QCString replaceColorMarkers(const QCString &str)
     p=i+l;
   }
   if (p<sl) result+=s.substr(p);
-  return result;
+  return QCString(result);
 }
 
 /** Copies the contents of file with name \a src to the newly created
@@ -7031,7 +7036,7 @@ bool mainPageHasTitle()
 
 QCString getDotImageExtension()
 {
-  QCString imgExt = Config_getEnum(DOT_IMAGE_FORMAT);
+  QCString imgExt = Config_getEnumAsString(DOT_IMAGE_FORMAT);
   int i= imgExt.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format
   return i==-1 ? imgExt : imgExt.left(i);
 }
@@ -7381,3 +7386,4 @@ QCString integerToRoman(int n, bool upper)
 
   return result;
 }
+
index 4b02827..4ed2041 100644 (file)
@@ -226,7 +226,7 @@ QCString convertToLaTeX(const QCString &s,bool insideTabbing=FALSE,bool keepSpac
 
 QCString convertToXML(const QCString &s, bool keepEntities=FALSE);
 
-QCString convertToDocBook(const QCString &s);
+QCString convertToDocBook(const QCString &s, const bool retainNewline = false);
 
 QCString convertToJSString(const QCString &s);
 
@@ -293,7 +293,8 @@ void filterLatexString(TextStream &t,const QCString &str,
                        bool insidePre,
                        bool insideItem,
                        bool insideTable,
-                       bool keepSpaces);
+                       bool keepSpaces,
+                       const bool retainNewline = false);
 
 QCString latexEscapeLabelName(const QCString &s);
 QCString latexEscapeIndexChars(const QCString &s);
index d04e5a6..7f0407e 100644 (file)
@@ -16,8 +16,6 @@
 #ifndef VARIANT_H
 #define VARIANT_H
 
-#include <typeinfo>
-#include <type_traits>
 #include <string>
 #include <utility>
 
@@ -50,99 +48,126 @@ struct TMax<arg1, arg2, others...>
 
 //------ helper class to deal with memory management of an array of template types
 
-//! generic declaration of a template to handle copyin, moving, deleting, and computing the
-//! index for a type that matches one in the set of template parameters.
-template<typename... Ts>
-struct HelperT;
-
-//! specialization to stop the recursion for an empty list.
-template<>
-struct HelperT<>
-{
-  inline static void   copy(size_t src_t, const void * src_v, void * dst_v) { }
-  inline static void   move(size_t src_t, void * src_v, void * dst_v) { }
-  inline static void   destroy(size_t id, void * data) { }
-  inline static size_t index(size_t id, size_t index) { return std::string::npos; }
-};
+//! generic declaration of a template to handle copying, moving, and deleting
+//! type that matches a given index in the list of variant parameters.
+template<uint8_t n,typename... Ts>
+struct HelperRecT;
 
 //! Recursive template definition for multiple arguments.
-//! Each function check the first parameter, and if the type matches does the action.
-//! If not, the same function is called without this template parameters.
-template<typename F, typename... Ts>
-struct HelperT<F, Ts...>
+//! Each function checks for a matching index, and if found does the action.
+//! If not, the same function is called with the next index and one less type argument.
+template<uint8_t n, typename F, typename... Ts>
+struct HelperRecT<n, F, Ts...>
 {
   //! Helper function to copy an instance of a type by performing a placement new.
-  //! @param src_t The id if the type to search for in the template parameter list
+  //! @param id The id if the type to search for in the template parameter list
   //! @param src_v A pointer to the value of the type to copy from.
   //! @param dst_v A pointer to the variable to copy to.
-  inline static void copy(size_t src_t, const void * src_v, void * dst_v)
+  inline static void copy(uint8_t id, const void * src_v, void * dst_v)
   {
-    if (src_t == typeid(F).hash_code()) // found it
+    if (n==id) // found it
     {
       new (dst_v) F(*reinterpret_cast<const F*>(src_v));
     }
     else // continue searching
     {
-      HelperT<Ts...>::copy(src_t, src_v, dst_v);
+      HelperRecT<n+1,Ts...>::copy(id, src_v, dst_v);
     }
   }
 
   //! Helper function to move an instance of a type by calling the move constructor on it.
-  //! @param src_t The id if the type to search for in the template parameter list
+  //! @param id The id if the type to search for in the template parameter list
   //! @param src_v A pointer to the value of the type to copy from.
   //! @param dst_v A pointer to the variable to copy to.
-  inline static void move(size_t src_t, void * src_v, void * dst_v)
+  inline static void move(uint8_t id, void * src_v, void * dst_v)
   {
-    if (src_t == typeid(F).hash_code()) // found it
+    if (n==id) // found it
     {
       new (dst_v) F(std::move(*reinterpret_cast<F*>(src_v)));
     }
     else // continue searching
     {
-      HelperT<Ts...>::move(src_t, src_v, dst_v);
+      HelperRecT<n+1,Ts...>::move(id, src_v, dst_v);
     }
   }
 
   //! Helper function to destroy an object of a given type by calling its destructor.
   //! @param id The id if the type to search for in the template parameter list
   //! @param data A pointer to the object to destroy
-  inline static void destroy(size_t id, void * data)
+  inline static void destroy(uint8_t id, void * data)
   {
-    if (id == typeid(F).hash_code()) // found it
+    if (n==id) // found it
     {
       reinterpret_cast<F*>(data)->~F();
     }
     else // continue searching
     {
-      HelperT<Ts...>::destroy(id, data);
+      HelperRecT<n+1,Ts...>::destroy(id, data);
     }
   }
 
-  //! Helper function to returns the index of a given type within the template parameter list
-  //! @param id The id to search for
-  //! @param index The index into the original template list
-  inline static size_t index(size_t id,size_t index)
-  {
-    if (id == typeid(F).hash_code()) // found it
-    {
-      return index;
-    }
-    else // continue searching
-    {
-      return HelperT<Ts...>::index(id,index+1);
-    }
-  }
+};
+
+//! Specialization to stop the recursion when the end of the list has reached
+template<uint8_t n>
+struct HelperRecT<n>
+{
+  inline static void copy(uint8_t id, const void * src_v, void * dst_v) { }
+  inline static void move(uint8_t id, void * src_v, void * dst_v) { }
+  inline static void destroy(uint8_t id, void * data) { }
+};
 
+//! Helper to kickstart the recursive search
+template<typename ...Ts>
+struct HelperT
+{
+  inline static void copy(uint8_t id, const void *src_v, void *dst_v)
+  { HelperRecT<0, Ts...>::copy(id, src_v, dst_v); }
+  inline static void move(uint8_t id, void *src_v, void *dst_v)
+  { HelperRecT<0, Ts...>::move(id, src_v, dst_v); }
+  inline static void destroy(uint8_t id,void *data)
+  { HelperRecT<0, Ts...>::destroy(id, data); }
+};
+
+//! Specialization to end the recursion
+template<>
+struct HelperT<>
+{
+  inline static void copy(uint8_t id, const void * src_v, void * dst_v) { }
+  inline static void move(uint8_t id, void * src_v, void * dst_v) { }
+  inline static void destroy(uint8_t id, void * data) { }
 };
 
 } // namespace details
 
+//! Generic declaration of a template type wrapper where VariantType<index,...>::type
+//! represents the type of the variant at the given index.
+//! The first type of the variant has index 0, the second has
+//! index 1, etc.
+template<uint8_t index, typename... Items>
+struct VariantType;
+
+//! specialization to stop the recursion when arrived at index 0 and type F
+template<typename F,typename...Ts>
+struct VariantType<0, F, Ts...>
+{
+  using type = F;
+};
+
+//! recursive definition of the type wrapper
+template<uint8_t index, typename F, typename... Ts>
+struct VariantType<index, F, Ts...>
+{
+  using type = typename VariantType<index-1,Ts...>::type;
+};
+
 //------------------------------------------------------------------
 
 //! Implementation of a variant container (similar to C++17's std::variant).
 //! It can hold either no instances (e.g. initially or after calling invalidate()),
 //! or hold exactly one instance of an object (after calling set())
 //! whose type is one of the variant's template parameters.
+//! Each parameter has an index, the first parameter has index 0.
 //! It behaves similar to a C union, in that the memory of all
 //! possible object types is shared, but unlike a C union
 //! it does allow C++ objects with constructors and destructors to be stored and
@@ -157,42 +182,49 @@ struct Variant {
 
     //! the data type for the Variant's internal memory
     using Data   = typename std::aligned_storage<data_size, data_align>::type;
+
     //! a short hand name for the helper class
     using HelperT = details::HelperT<Ts...>;
 
+    template<uint8_t index>
+    using Type = typename VariantType<index,Ts...>::type;
+
     //! The id that represents an invalid type
-    static inline size_t invalid_type() { return typeid(void).hash_code(); }
+    static inline uint8_t invalid_id() { return 255; }
 
-    //! a unique identifier for the type held by this variant
-    size_t type_id;
     //! the actual data
-    Data data;
+    Data m_data;
+    //! a unique identifier for the type held by this variant
+    uint8_t m_id;
 
   public:
     //! The default constructor
-    Variant() : type_id(invalid_type())
+    Variant() : m_id(invalid_id())
     {
     }
 
     //! The copy constructor
-    Variant(const Variant<Ts...>& src) : type_id(src.type_id)
+    Variant(const Variant<Ts...>& src) : m_id(src.m_id)
     {
-      HelperT::copy(src.type_id, &src.data, &data);
+      HelperT::copy(src.m_id, &src.m_data, &m_data);
     }
 
     //! The move constructor
-    Variant(Variant<Ts...>&& src) : type_id(src.type_id)
+    Variant(Variant<Ts...>&& src) : m_id(src.m_id)
     {
-      HelperT::move(src.type_id, &src.data, &data);
+      HelperT::move(src.m_id, &src.m_data, &m_data);
     }
 
     //! The copy assignment operator
     Variant<Ts...>& operator= (const Variant<Ts...> &src)
     {
-      if (this!=&src)
+      if (this!=&src) // prevent self assignment
       {
-        type_id = src.type_id;
-        HelperT::copy(src.type_id, &src.data, &data);
+        // destroy the old value
+        if (valid()) HelperT::destroy(m_id,&m_data);
+        // and copy over the new one
+        m_id = src.m_id;
+        HelperT::copy(src.m_id, &src.m_data, &m_data);
       }
       return *this;
     }
@@ -200,67 +232,70 @@ struct Variant {
     //! The move assignment operator
     Variant<Ts...>& operator= (Variant<Ts...> &&src)
     {
-      type_id = src.type_id;
-      HelperT::move(src.type_id, &src.data, &data);
+      // destroy the old value
+      if (valid()) HelperT::destroy(m_id,&m_data);
+      // and move in the new one
+      m_id = src.m_id;
+      HelperT::move(src.m_id, &src.m_data, &m_data);
       return *this;
     }
 
     //! The destructor
     ~Variant()
     {
-      HelperT::destroy(type_id, &data);
+      HelperT::destroy(m_id, &m_data);
     }
 
     //! Returns true iff the variant container holds a specific type.
     //! @tparam T the type to search for.
-    template<typename T>
-    constexpr bool is() const { return (type_id==typeid(T).hash_code()); }
+    template<uint8_t index>
+    constexpr bool is() const { return m_id==index; }
 
     //! Returns true iff the Variant holds a valid type.
-    constexpr bool valid() const { return (type_id!=invalid_type()); }
+    constexpr bool valid() const { return m_id!=invalid_id(); }
 
     //! Invalidate the variant. Will destroy any object that is held.
     void invalidate()
     {
-      HelperT::destroy(type_id,&data);
-      type_id = invalid_type();
+      HelperT::destroy(m_id,&m_data);
+      m_id = invalid_id();
     }
 
-    //! Returns the index of the type held by this variant, or std::string::npos if the
+    //! Returns the index of the type held by this variant, or invalid_id() if the
     //! variant does not hold any type (i.e. valid() returns false).
-    constexpr size_t index() const { return HelperT::index(type_id, 0); }
+    constexpr uint8_t index() const { return m_id; }
 
     //! Replaces the contents of the variant container by constructing a type T calling
     //! the constructor with Args
-    //! @tparam T the type to make the variant hold an instance of.
+    //! @tparam index the type to make the variant hold an instance of.
     //! @tparam Args The arguments types to pass to the constructor of T.
     //! @param args The argument values
-    template<typename T, typename... Args>
+    template<uint8_t index, typename... Args>
     void set(Args&&... args)
     {
-      HelperT::destroy(type_id, &data);
-      new (&data) T(std::forward<Args>(args)...);
-      type_id = typeid(T).hash_code();
+      HelperT::destroy(m_id, &m_data);
+      m_id = index;
+      new (&m_data) Type<index>(std::forward<Args>(args)...);
     }
 
     //! Return a non-constant reference to the value held by the variant container.
     //! @throw std::bad_cast() if called on a variant container that does not hold
-    //! an instance of the specified type.
-    template<typename T>
-    T& get()
+    //! an instance of the type of the variant at index.
+    template<uint8_t index>
+    Type<index>& get()
     {
-      if (type_id != typeid(T).hash_code()) throw std::bad_cast();
-      return *reinterpret_cast<T*>(&data);
+      if (m_id != index) throw std::bad_cast();
+      return *reinterpret_cast<Type<index>*>(&m_data);
     }
 
     //! Returns a constant reference to the value held by the variant container.
     //! @throw std::bad_cast() if called on a variant container that does not hold
-    //! an instance of the specified type.
-    template<typename T>
-    const T& get() const
+    //! an instance of the type of the variant at index.
+    template<uint8_t index>
+    const Type<index>& get() const
     {
-      if (type_id != typeid(T).hash_code()) throw std::bad_cast();
-      return *reinterpret_cast<const T*>(&data);
+      if (m_id != index) throw std::bad_cast();
+      return *reinterpret_cast<const Type<index>*>(&m_data);
     }
 
 };
index 12b0bc9..2e11f9e 100644 (file)
 %option extra-type="struct vhdlcodeYY_state *"
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -76,7 +80,6 @@ struct vhdlcodeYY_state
   bool          isComponent = false;
   bool          isPackageBody = false;
   bool          isProto = false;
-  bool          startCode = false;
   QCString      prevString;
   QCString      currClass;
   std::unordered_set<std::string> vhdlKeyDict;
@@ -88,9 +91,10 @@ struct vhdlcodeYY_state
   CodeOutputInterface * code = 0;
   const char *  inputString = 0;     //!< the code fragment as text
   yy_size_t     inputPosition = 0;   //!< read offset during parsing
+  QCString      fileName;
   int           inputLines = 0;      //!< number of line in the code fragment
   int           yyLineNr = 0;        //!< current line number
-  bool          needsTermination = false;
+  bool          insideCodeLine = false;
   const Definition *searchCtx = 0;
 
   bool          exampleBlock = false;
@@ -145,6 +149,10 @@ static const char *stateToString(int state);
 #undef        YY_INPUT
 #define       YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
+
 %}
 
 
@@ -202,13 +210,9 @@ XILINX      "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI
 %x ParseComponent
 %x ParsePackage
 %x ParseProcessProto
-%x ClassName
-%x PackageName
-%x ClassVar
 %x ClassesName
 %x Map
 %x End
-%x Body
 
 %%
 
@@ -1034,24 +1038,27 @@ static void startCodeLine(yyscan_t yyscanner)
       {
         yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
                                 yyextra->currentMemberDef->getOutputFileBase(),
-                                yyextra->currentMemberDef->anchor(),yyextra->yyLineNr);
+                                yyextra->currentMemberDef->anchor(),yyextra->yyLineNr,
+                                !yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
       else if (d->isLinkableInProject())
       {
         yyextra->code->writeLineNumber(d->getReference(),
                                 d->getOutputFileBase(),
-                                QCString(),yyextra->yyLineNr);
+                                QCString(),yyextra->yyLineNr,
+                                !yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
     }
     else
     {
-      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr);
+      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr,
+                                     !yyextra->includeCodeFragment);
     }
   }
   yyextra->code->startCodeLine(yyextra->sourceFileDef);
-  yyextra->startCode=true;
+  yyextra->insideCodeLine=true;
   if (yyextra->currentFontClass)
   {
     yyextra->code->startFontClass(yyextra->currentFontClass);
@@ -1063,12 +1070,13 @@ static void endCodeLine(yyscan_t yyscanner)
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   endFontClass(yyscanner);
   yyextra->code->endCodeLine();
+  yyextra->insideCodeLine=false;
 }
 
 static void nextCodeLine(yyscan_t yyscanner)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
-  if (yyextra->startCode)
+  if (yyextra->insideCodeLine)
   {
     endCodeLine(yyscanner);    // </div>
   }
@@ -1386,8 +1394,7 @@ static int countLines(yyscan_t yyscanner)
   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++,
-    yyextra->needsTermination=true;
+    count++;
   }
   return count;
 }
@@ -1594,6 +1601,7 @@ void VHDLCodeParser::parseCode(CodeOutputInterface &od,
   //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd);
   if (s.isEmpty()) return;
   printlex(yy_flex_debug, true, __FILE__, fd ? qPrint(fd->fileName()): NULL);
+  yyextra->fileName      = fd ? fd->fileName():"";
   if (memberDef)
   {
     const ClassDef *dd=memberDef->getClassDef();
@@ -1604,7 +1612,7 @@ void VHDLCodeParser::parseCode(CodeOutputInterface &od,
   yyextra->inputString   = s.data();
   yyextra->inputPosition = 0;
   yyextra->currentFontClass = 0;
-  yyextra->needsTermination = false;
+  yyextra->insideCodeLine = false;
   yyextra->searchCtx = searchCtx;
 
   if (startLine!=-1)
@@ -1647,11 +1655,10 @@ void VHDLCodeParser::parseCode(CodeOutputInterface &od,
     VhdlDocGen::init();
     yyextra->lexInit=true;
   }
-  /*int iLine=*/countLines(yyscanner);
   vhdlcodeYYrestart( 0, yyscanner );
   BEGIN( Bases );
   vhdlcodeYYlex(yyscanner);
-  if (yyextra->needsTermination)
+  if (yyextra->insideCodeLine)
   {
     endCodeLine(yyscanner);
   }
@@ -1661,7 +1668,6 @@ void VHDLCodeParser::parseCode(CodeOutputInterface &od,
     delete yyextra->sourceFileDef;
     yyextra->sourceFileDef=0;
   }
-  yyextra->startCode=false;
 
   // write the tooltips
   yyextra->tooltipManager.writeTooltips(od);
index d75c879..8793e58 100644 (file)
@@ -81,6 +81,7 @@ static void writeTable(const std::vector<const MemberDef*> &portList,TextStream
 static void endTable(TextStream &t);
 static void writeClassToDot(TextStream &t,ClassDef* cd);
 static void writeVhdlDotLink(TextStream &t,const QCString &a,const QCString &b,const QCString &style);
+
 static const MemberDef *flowMember=0;
 
 void VhdlDocGen::setFlowMember( const MemberDef* mem)
@@ -335,7 +336,7 @@ static void writeColumn(TextStream &t,const MemberDef *md,bool start)
   if (md)
   {
     t << "href=\"";
-    t << md->getOutputFileBase()<< Doxygen::htmlFileExtension;
+    t << addHtmlExtensionIfMissing(md->getOutputFileBase());
     t << "#" << md->anchor();
     t<<"\" ";
 
@@ -405,7 +406,7 @@ static void writeClassToDot(TextStream &t,ClassDef* cd)
   t << cd->name();
   t << "\" ";
   t << "href=\"";
-  t << cd->getOutputFileBase() << Doxygen::htmlFileExtension;
+  t << addHtmlExtensionIfMissing(cd->getOutputFileBase());
   t << "\" ";
   t << ">";
   t << cd->name();
@@ -1726,7 +1727,7 @@ void VhdlDocGen::writeTagFile(MemberDefMutable *mdef,TextStream &tagFile)
   tagFile << "\">\n";
   tagFile << "      <type>" << convertToXML(mdef->typeString()) << "</type>\n";
   tagFile << "      <name>" << convertToXML(mdef->name()) << "</name>\n";
-  tagFile << "      <anchorfile>" << convertToXML(mdef->getOutputFileBase()) << Doxygen::htmlFileExtension << "</anchorfile>\n";
+  tagFile << "      <anchorfile>" << convertToXML(addHtmlExtensionIfMissing(mdef->getOutputFileBase())) << "</anchorfile>\n";
   tagFile << "      <anchor>" << convertToXML(mdef->anchor()) << "</anchor>\n";
 
   if (VhdlDocGen::isVhdlFunction(mdef))
@@ -2465,7 +2466,7 @@ QCString  VhdlDocGen::parseForBinding(QCString & entity,QCString & arch)
   {
     arch=ql[2];
   }
-  return label;
+  return QCString(label);
 }
 
 
index e5c74aa..c3e7f51 100644 (file)
 %option noyywrap
 %top{
 #include <stdint.h>
+// forward declare yyscan_t to improve type safety
+#define YY_TYPEDEF_YY_SCANNER_T
+struct yyguts_t;
+typedef yyguts_t *yyscan_t;
 }
 
 %{
@@ -57,9 +61,10 @@ struct xmlcodeYY_state
   QCString      parmName;
   const char *  inputString = 0;     //!< the code fragment as text
   yy_size_t     inputPosition = 0;   //!< read offset during parsing
+  QCString      fileName;
   int           inputLines = 0;      //!< number of line in the code fragment
   int           yyLineNr = 0;        //!< current line number
-  bool          needsTermination = false;
+  bool          insideCodeLine = false;
   const Definition   *searchCtx = 0;
 
   bool          exampleBlock = false;
@@ -98,6 +103,10 @@ static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
 #undef YY_INPUT
 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
 
+// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
+static inline const char *getLexerFILE() {return __FILE__;}
+#include "doxygen_lex.h"
+
 %}
 
 nl          (\r\n|\r|\n)
@@ -253,24 +262,28 @@ static void startCodeLine(yyscan_t yyscanner)
       {
         yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
                             yyextra->currentMemberDef->getOutputFileBase(),
-                            yyextra->currentMemberDef->anchor(),yyextra->yyLineNr);
+                            yyextra->currentMemberDef->anchor(),yyextra->yyLineNr,
+                            !yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
       else
       {
         yyextra->code->writeLineNumber(d->getReference(),
                             d->getOutputFileBase(),
-                            QCString(),yyextra->yyLineNr);
+                            QCString(),yyextra->yyLineNr,
+                            !yyextra->includeCodeFragment);
         setCurrentDoc(yyscanner,lineAnchor);
       }
     }
     else
     {
-      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr);
+      yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr,
+                                     !yyextra->includeCodeFragment);
     }
   }
 
   yyextra->code->startCodeLine(yyextra->sourceFileDef);
+  yyextra->insideCodeLine = true;
 
   if (yyextra->currentFontClass)
   {
@@ -293,13 +306,17 @@ static void endCodeLine(yyscan_t yyscanner)
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   endFontClass(yyscanner);
   yyextra->code->endCodeLine();
+  yyextra->insideCodeLine = false;
 }
 
 static void nextCodeLine(yyscan_t yyscanner)
 {
   struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
   const char *fc = yyextra->currentFontClass;
-  endCodeLine(yyscanner);
+  if (yyextra->insideCodeLine)
+  {
+    endCodeLine(yyscanner);
+  }
   if (yyextra->yyLineNr<yyextra->inputLines)
   {
     yyextra->currentFontClass = fc;
@@ -359,8 +376,7 @@ static int countLines(yyscan_t yyscanner)
   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++,
-    yyextra->needsTermination=true;
+    count++;
   }
   return count;
 }
@@ -416,12 +432,13 @@ void XMLCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
   if (input.isEmpty()) return;
 
   printlex(yy_flex_debug, true, __FILE__, fileDef ? qPrint(fileDef->fileName()): NULL);
+  yyextra->fileName      = fileDef ? fileDef->fileName():"";
 
   yyextra->code = &codeOutIntf;
   yyextra->inputString   = input.data();
   yyextra->inputPosition = 0;
   yyextra->currentFontClass = 0;
-  yyextra->needsTermination = false;
+  yyextra->insideCodeLine = false;
   yyextra->searchCtx = searchCtx;
 
   if (startLine!=-1)
@@ -460,7 +477,7 @@ void XMLCodeParser::parseCode(CodeOutputInterface &codeOutIntf,
 
   xmlcodeYYlex(yyscanner);
 
-  if (yyextra->needsTermination)
+  if (yyextra->insideCodeLine)
   {
     endCodeLine(yyscanner);
   }
index 00c976c..c0e0271 100644 (file)
@@ -38,7 +38,7 @@ static void visitCaption(XmlDocVisitor *parent, const DocNodeList &children)
 static void visitPreStart(TextStream &t, const char *cmd, bool doCaption,
                           XmlDocVisitor *parent, const DocNodeList &children,
                           const QCString &name, bool writeType, DocImage::Type type, const QCString &width,
-                          const QCString &height, const QCString &alt = QCString(""), bool inlineImage = FALSE)
+                          const QCString &height, const QCString engine = QCString(), const QCString &alt = QCString(), bool inlineImage = FALSE)
 {
   t << "<" << cmd;
   if (writeType)
@@ -50,6 +50,7 @@ static void visitPreStart(TextStream &t, const char *cmd, bool doCaption,
       case DocImage::Latex:   t << "latex"; break;
       case DocImage::Rtf:     t << "rtf"; break;
       case DocImage::DocBook: t << "docbook"; break;
+      case DocImage::Xml:     t << "xml"; break;
     }
     t << "\"";
   }
@@ -65,6 +66,10 @@ static void visitPreStart(TextStream &t, const char *cmd, bool doCaption,
   {
     t << " height=\"" << convertToXML(height) << "\"";
   }
+  if (!engine.isEmpty())
+  {
+    t << " engine=\"" << convertToXML(engine) << "\"";
+  }
   if (!alt.isEmpty())
   {
     t << " alt=\"" << convertToXML(alt) << "\"";
@@ -220,6 +225,9 @@ void XmlDocVisitor::visit(DocStyleChange *s)
     case DocStyleChange::Small:
       if (s->enable()) m_t << "<small>";  else m_t << "</small>";
       break;
+    case DocStyleChange::Cite:
+      if (s->enable()) m_t << "<cite>";  else m_t << "</cite>";
+      break;
     case DocStyleChange::Preformatted:
       if (s->enable())
       {
@@ -234,6 +242,12 @@ void XmlDocVisitor::visit(DocStyleChange *s)
       break;
     case DocStyleChange::Div:  /* HTML only */ break;
     case DocStyleChange::Span: /* HTML only */ break;
+    case DocStyleChange::Details:
+      if (s->enable()) m_t << "<details>";  else m_t << "</details>";
+      break;
+    case DocStyleChange::Summary:
+      if (s->enable()) m_t << "<summary>";  else m_t << "</summary>";
+      break;
   }
 }
 
@@ -258,6 +272,16 @@ void XmlDocVisitor::visit(DocVerbatim *s)
                                     s->isExample(),s->exampleFile());
       m_t << "</programlisting>";
       break;
+    case DocVerbatim::JavaDocLiteral:
+      m_t << "<javadocliteral>";
+      filter(s->text());
+      m_t << "</javadocliteral>";
+      break;
+    case DocVerbatim::JavaDocCode:
+      m_t << "<javadoccode>";
+      filter(s->text());
+      m_t << "</javadoccode>";
+      break;
     case DocVerbatim::Verbatim:
       m_t << "<verbatim>";
       filter(s->text());
@@ -309,7 +333,7 @@ void XmlDocVisitor::visit(DocVerbatim *s)
       visitPostEnd(m_t, "msc");
       break;
     case DocVerbatim::PlantUML:
-      visitPreStart(m_t, "plantuml", s->hasCaption(), this, s->children(),  QCString(""), FALSE, DocImage::Html, s->width(), s->height());
+      visitPreStart(m_t, "plantuml", s->hasCaption(), this, s->children(),  QCString(""), FALSE, DocImage::Html, s->width(), s->height(), s->engine());
       filter(s->text());
       visitPostEnd(m_t, "plantuml");
       break;
@@ -731,10 +755,18 @@ void XmlDocVisitor::visitPost(DocHtmlList *s)
     m_t << "</itemizedlist>\n";
 }
 
-void XmlDocVisitor::visitPre(DocHtmlListItem *)
+void XmlDocVisitor::visitPre(DocHtmlListItem *l)
 {
   if (m_hide) return;
-  m_t << "<listitem>\n";
+  m_t << "<listitem";
+  for (const auto &opt : l->attribs())
+  {
+    if (opt.name=="value")
+    {
+      m_t << " " << opt.name << "=\"" << opt.value << "\"";
+    }
+  }
+  m_t << ">\n";
 }
 
 void XmlDocVisitor::visitPost(DocHtmlListItem *)
@@ -792,6 +824,16 @@ void XmlDocVisitor::visitPre(DocHtmlTable *t)
     }
   }
   m_t << ">";
+  if (t->hasCaption())
+  {
+    DocHtmlCaption *c = t->caption();
+    m_t << "<caption";
+    if (!c->file().isEmpty())
+    {
+      m_t << " id=\""  << stripPath(c->file()) << "_1" << c->anchor() << "\"";
+    }
+    m_t << ">";
+  }
 }
 
 void XmlDocVisitor::visitPost(DocHtmlTable *)
@@ -872,7 +914,7 @@ void XmlDocVisitor::visitPost(DocHtmlCell *)
 void XmlDocVisitor::visitPre(DocHtmlCaption *)
 {
   if (m_hide) return;
-  m_t << "<caption>";
+  // start of caption is handled in the XmlDocVisitor::visitPre(DocHtmlTable *t)
 }
 
 void XmlDocVisitor::visitPost(DocHtmlCaption *)
@@ -936,7 +978,7 @@ void XmlDocVisitor::visitPre(DocImage *img)
                          [](const auto &att) { return att.name=="alt"; });
   QCString altValue = it!=attribs.end() ? it->value : "";
   visitPreStart(m_t, "image", FALSE, this, img->children(), baseName, TRUE,
-                img->type(), img->width(), img->height(),
+                img->type(), img->width(), img->height(), QCString(),
                 altValue, img->isInlineImage());
 
   // copy the image to the output dir
@@ -957,7 +999,8 @@ void XmlDocVisitor::visitPost(DocImage *)
 void XmlDocVisitor::visitPre(DocDotFile *df)
 {
   if (m_hide) return;
-  visitPreStart(m_t, "dotfile", FALSE, this, df->children(), df->file(), FALSE, DocImage::Html, df->width(), df->height());
+  copyFile(df->file(),Config_getString(XML_OUTPUT)+"/"+stripPath(df->file()));
+  visitPreStart(m_t, "dotfile", FALSE, this, df->children(), stripPath(df->file()), FALSE, DocImage::Html, df->width(), df->height());
 }
 
 void XmlDocVisitor::visitPost(DocDotFile *)
@@ -969,7 +1012,8 @@ void XmlDocVisitor::visitPost(DocDotFile *)
 void XmlDocVisitor::visitPre(DocMscFile *df)
 {
   if (m_hide) return;
-  visitPreStart(m_t, "mscfile", FALSE, this, df->children(), df->file(), FALSE, DocImage::Html, df->width(), df->height());
+  copyFile(df->file(),Config_getString(XML_OUTPUT)+"/"+stripPath(df->file()));
+  visitPreStart(m_t, "mscfile", FALSE, this, df->children(), stripPath(df->file()), FALSE, DocImage::Html, df->width(), df->height());
 }
 
 void XmlDocVisitor::visitPost(DocMscFile *)
@@ -981,7 +1025,8 @@ void XmlDocVisitor::visitPost(DocMscFile *)
 void XmlDocVisitor::visitPre(DocDiaFile *df)
 {
   if (m_hide) return;
-  visitPreStart(m_t, "diafile", FALSE, this, df->children(), df->file(), FALSE, DocImage::Html, df->width(), df->height());
+  copyFile(df->file(),Config_getString(XML_OUTPUT)+"/"+stripPath(df->file()));
+  visitPreStart(m_t, "diafile", FALSE, this, df->children(), stripPath(df->file()), FALSE, DocImage::Html, df->width(), df->height());
 }
 
 void XmlDocVisitor::visitPost(DocDiaFile *)
index f12a52d..14797b5 100644 (file)
@@ -325,7 +325,7 @@ void XMLCodeGenerator::writeCodeAnchor(const QCString &)
   XML_DB(("(writeCodeAnchor)\n"));
 }
 void XMLCodeGenerator::writeLineNumber(const QCString &extRef,const QCString &compId,
-                     const QCString &anchorId,int l)
+                     const QCString &anchorId,int l,bool)
 {
   XML_DB(("(writeLineNumber)\n"));
   // we remember the information provided here to use it
@@ -568,12 +568,6 @@ static void generateXMLForMember(const MemberDef *md,TextStream &ti,TextStream &
      << "_1" << md->anchor() << "\" kind=\"" << memType << "\"><name>"
      << convertToXML(md->name()) << "</name></member>\n";
 
-  QCString scopeName;
-  if (md->getClassDef())
-    scopeName=md->getClassDef()->name();
-  else if (md->getNamespaceDef())
-    scopeName=md->getNamespaceDef()->name();
-
   t << "      <memberdef kind=\"";
   //enum { define_t,variable_t,typedef_t,enum_t,function_t } xmlType = function_t;
   t << memType << "\" id=\"";
@@ -819,7 +813,13 @@ static void generateXMLForMember(const MemberDef *md,TextStream &ti,TextStream &
     t << "</type>\n";
   }
 
-  t << "        <name>" << convertToXML(md->name()) << "</name>\n";
+  QCString name = md->name();
+  QCString qualifiedName = md->qualifiedName();;
+  t << "        <name>" << convertToXML(name) << "</name>\n";
+  if (name!=qualifiedName)
+  {
+    t << "        <qualifiedname>" << convertToXML(qualifiedName) << "</qualifiedname>\n";
+  }
 
   if (md->memberType() == MemberType_Property)
   {
index b28384a..7adda71 100644 (file)
@@ -38,7 +38,7 @@ class XMLCodeGenerator : public CodeOutputInterface
     void endFontClass() override;
     void writeCodeAnchor(const QCString &) override;
     void writeLineNumber(const QCString &extRef,const QCString &compId,
-                         const QCString &anchorId,int l) override;
+                         const QCString &anchorId,int l,bool writeLineAnchor) override;
     void setCurrentDoc(const Definition *,const QCString &,bool) override {}
     void addWord(const QCString &,bool) override {}
     void startCodeFragment(const QCString &) override;
index 539aaab..99e569e 100755 (executable)
@@ -58,6 +58,8 @@ sub html_ent {
        s/\!\`/&iexcl;/g;
        s/\-\-\-/&mdash;/g;
        s/([^\!])\-\-([^\>])/$1&ndash;$2/g;
+       s/(CITEREF_[^\!])&ndash;([^\>])/$1--$2/g;
+       s/(CITEREF_[^\!])&mdash;([^\>])/$1---$2/g;
        s/\\([aA]lpha)\b/&$1;/g;
        s/\\([bB]eta)\b/&$1;/g;
        s/\\([gG]amma)\b/&$1;/g;
index 0872335..4087c87 100644 (file)
@@ -262,7 +262,7 @@ dl.el {
 }
 
 ul {
-  overflow: hidden; /*Fixed: list item bullets overlap floating elements*/
+  overflow: visible;
 }
 
 #side-nav ul {
@@ -1356,6 +1356,11 @@ dl.section dd {
 }
 
 
+#projectrow
+{
+       height: 56px;
+}
+
 #projectlogo
 {
        text-align: center;
@@ -1371,6 +1376,7 @@ dl.section dd {
 #projectalign
 {
         vertical-align: middle;
+        padding-left: 0.5em;
 }
 
 #projectname
@@ -1521,6 +1527,10 @@ span.emoji {
          */
 }
 
+span.obfuscator {
+  display: none;
+}
+
 .PageDocRTL-title div.toc li.level1 {
   margin-left: 0 !important;
   margin-right: 0;
@@ -1575,7 +1585,7 @@ tr.heading h2 {
 
 #powerTip {
        cursor: default;
-       white-space: nowrap;
+       /*white-space: nowrap;*/
        background-color: white;
        border: 1px solid gray;
        border-radius: 4px 4px 4px 4px;
@@ -1814,6 +1824,10 @@ table.DocNodeLTR {
    margin-left: 0;
 }
 
+code.JavaDocCode
+  direction:ltr;
+}
+
 tt, code, kbd, samp
 {
   display: inline-block;
index ddc333a..0149b8b 100644 (file)
@@ -1,6 +1,7 @@
 $(document).ready(function() {
   $('.code,.codeRef').each(function() {
     $(this).data('powertip',$('#a'+$(this).attr('href').replace(/.*\//,'').replace(/[^a-z_A-Z0-9]/g,'_')).html());
+    $.fn.powerTip.smartPlacementLists.s = [ 's', 'n', 'ne', 'se' ];
     $(this).powerTip({ placement: 's', smartPlacement: true, mouseOnToPopup: true });
   });
 });
index 8db982e..adf16b6 100644 (file)
@@ -34,12 +34,12 @@ $extrastylesheet
 <div id="titlearea">
 <table cellspacing="0" cellpadding="0">
  <tbody>
- <tr style="height: 56px;">
+ <tr id="projectrow">
   <!--BEGIN PROJECT_LOGO-->
   <td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
   <!--END PROJECT_LOGO-->
   <!--BEGIN PROJECT_NAME-->
-  <td id="projectalign" style="padding-left: 0.5em;">
+  <td id="projectalign">
    <div id="projectname">$projectname<!--BEGIN PROJECT_NUMBER--><span id="projectnumber">&#160;$projectnumber</span><!--END PROJECT_NUMBER-->
    </div>
    <!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
@@ -47,7 +47,7 @@ $extrastylesheet
   <!--END PROJECT_NAME-->
   <!--BEGIN !PROJECT_NAME-->
    <!--BEGIN PROJECT_BRIEF-->
-    <td style="padding-left: 0.5em;">
+    <td>
     <div id="projectbrief">$projectbrief</div>
     </td>
    <!--END PROJECT_BRIEF-->
index e345441..4fba0e3 100644 (file)
@@ -91,11 +91,11 @@ MathJax.Hub.Config({
 <div id="titlearea">
 <table cellspacing="0" cellpadding="0">
  <tbody>
- <tr style="height: 56px;">
+ <tr id="projectrow">
  {% if config.PROJECT_LOGO %}
   <td id="projectlogo"><img alt="Logo" src="{{ page.relPath }}{{ config.PROJECT_LOGO|stripPath }}"/></td>
  {% endif %}
-  <td id="projectalign" style="padding-left: 0.5em;">
+  <td id="projectalign">
  {% if config.PROJECT_NAME %}
    <div id="projectname">{{ config.PROJECT_NAME }}{% if config.PROJECT_NUMBER %}<span id="projectnumber">&#160;{{ config.PROJECT_NUMBER }}</span>{% endif %}
    </div>
@@ -233,7 +233,10 @@ $(document).ready(function(){initNavTree('{{ page.fileName }}{% if page_postfix
 {% block title %}
 {% if page.title %}
   <div class="headertitle">
-  <div class="title">{{ page.title }}</div></div>
+  <div class="title">{{ page.title }}
+  {% block ingroups %}
+  {% endblock %}
+  </div></div>
 {% endif %}
 {% endblock %}
 </div><!-- header -->
index d5175af..6e2af50 100644 (file)
@@ -9,6 +9,10 @@
 {% endif %}
 {% endblock %}
 
+{% block ingroups %}
+{% include 'htmlpartofgroups.tpl' %}
+{% endblock %}
+
 {% block title %}
   {# write summary links in the title area #}
   <div class="summary">
index a57262f..1cc5838 100644 (file)
@@ -9,6 +9,10 @@
 {% endif %}
 {% endblock %}
 
+{% block ingroups %}
+{% include 'htmlpartofgroups.tpl' %}
+{% endblock %}
+
 {% block title %}
   {{ block.super }}
 {% endblock %}
index aeb2fa5..7584dc1 100644 (file)
@@ -9,6 +9,10 @@
   {% endif %}
 {% endblock %}
 
+{% block ingroups %}
+{% include 'htmlpartofgroups.tpl' %}
+{% endblock %}
+
 {% block title %}
   {# write summary links in the title area #}
   <div class="summary">
index 80e2826..fcbad6e 100644 (file)
@@ -9,6 +9,10 @@
   {% endif %}
 {% endblock %}
 
+{% block ingroups %}
+{% include 'htmlpartofgroups.tpl' %}
+{% endblock %}
+
 {% block title %}
   {# write summary links in the title area #}
   <div class="summary">
index 84eca23..d6bce5b 100644 (file)
@@ -4,6 +4,7 @@
     <h2 class="groupheader">{{ memberListInfo.title }}</h2>
     {% for member in memberListInfo.members %}
       {% if member.detailsVisibleFor:compound.compoundKind %}
+      <a id="{{ member.anchor }}" name="{{ member.anchor }}"></a>
       <h2 class="memtitle"><span class="permalink"><a href="#{{ member.anchor }}">&#9670;&nbsp;</a></span>{{ member.name }}{% if member.isFunction and not member.isObjCMethod %}(){% endif %}
       {% if memberListInfo.members|length>1 %}<span class="overload">[{{ forloop.counter }}/{{ memberListInfo.members|length }}]</a>{% endif %}
       </h2>
index 13196e2..27ccad4 100644 (file)
@@ -9,6 +9,10 @@
   {% endif %}
 {% endblock %}
 
+{% block ingroups %}
+{% include 'htmlpartofgroups.tpl' %}
+{% endblock %}
+
 {% block title %}
   {# write summary links in the title area #}
   <div class="summary">
index d359efa..2552573 100644 (file)
@@ -9,6 +9,10 @@
 {% endif %}
 {% endblock %}
 
+{% block ingroups %}
+{% include 'htmlpartofgroups.tpl' %}
+{% endblock %}
+
 {% block title %}
   {# write summary links in the title area #}
   <div class="summary">
index 74396e7..c0d5739 100644 (file)
@@ -9,6 +9,10 @@
   {% endif %}
 {% endblock %}
 
+{% block ingroups %}
+{% include 'htmlpartofgroups.tpl' %}
+{% endblock %}
+
 {% block content %}
 <div class="contents">
 {% if isMainPage and config.DISABLE_INDEX %}
diff --git a/templates/html/htmlparentgroup.tpl b/templates/html/htmlparentgroup.tpl
new file mode 100644 (file)
index 0000000..f4f9dd2
--- /dev/null
@@ -0,0 +1,12 @@
+{% for group in groups %}
+  {% if group.partOfGroups %}
+    {% with groups=group.partOfGroups %}
+      {% include 'htmlparentgroup.tpl' %}
+    {% endwith %}
+  {% endif %}
+  {% with obj=group text=group.title %}
+    {% include 'htmlobjlink.tpl' %}
+  {% endwith %}
+  {% if not forloop.last %} &#124; {% endif %}
+{% endfor %}
+&raquo;
diff --git a/templates/html/htmlpartofgroups.tpl b/templates/html/htmlpartofgroups.tpl
new file mode 100644 (file)
index 0000000..3acbbc4
--- /dev/null
@@ -0,0 +1,16 @@
+{# input compound #}
+{% if compound.partOfGroups %}
+<div class="ingroups">
+  {% for group in compound.partOfGroups %}
+    {% if group.partOfGroups %}
+      {% with groups=group.partOfGroups %}
+        {% include 'htmlparentgroup.tpl' %}
+      {% endwith %}
+    {% endif %}
+    {% with obj=group text=group.title %}
+      {% include 'htmlobjlink.tpl' %}
+    {% endwith %}
+    {% if not forloop.last %} &#124; {% endif %}
+  {% endfor %}
+</div>
+{% endif %}
index 8d9535a..7e01991 100644 (file)
@@ -23,6 +23,7 @@
 \RequirePackage{enumitem}
 \RequirePackage{alphalph}
 \RequirePackage[normalem]{ulem} % for strikeout, but don't modify emphasis
+\RequirePackage{enumitem}
 
 %---------- Internal commands used in this style file ----------------
 
 }
 
 % Used by numbered lists (using '-#' or <ol> ... </ol>)
-\newenvironment{DoxyEnumerate}{%
-  \enumerate%
-}{%
-  \endenumerate%
-}
+\setlistdepth{12}
+\newlist{DoxyEnumerate}{enumerate}{12}
+\setlist[DoxyEnumerate,1]{label=\arabic*.}
+\setlist[DoxyEnumerate,2]{label=(\enumalphalphcnt*)}
+\setlist[DoxyEnumerate,3]{label=\roman*.}
+\setlist[DoxyEnumerate,4]{label=\enumAlphAlphcnt*.}
+\setlist[DoxyEnumerate,5]{label=\arabic*.}
+\setlist[DoxyEnumerate,6]{label=(\enumalphalphcnt*)}
+\setlist[DoxyEnumerate,7]{label=\roman*.}
+\setlist[DoxyEnumerate,8]{label=\enumAlphAlphcnt*.}
+\setlist[DoxyEnumerate,9]{label=\arabic*.}
+\setlist[DoxyEnumerate,10]{label=(\enumalphalphcnt*)}
+\setlist[DoxyEnumerate,11]{label=\roman*.}
+\setlist[DoxyEnumerate,12]{label=\enumAlphAlphcnt*.}
 
 % Used by bullet lists (using '-', @li, @arg, or <ul> ... </ul>)
-\newenvironment{DoxyItemize}{%
-  \itemize%
-}{%
-  \enditemize%
-}
+\setlistdepth{12}
+\newlist{DoxyItemize}{itemize}{12}
+\setlist[DoxyItemize]{label=\textperiodcentered}
+
+\setlist[DoxyItemize,1]{label=\textbullet}
+\setlist[DoxyItemize,2]{label=\normalfont\bfseries \textendash}
+\setlist[DoxyItemize,3]{label=\textasteriskcentered}
+\setlist[DoxyItemize,4]{label=\textperiodcentered}
 
 % Used by description lists (using <dl> ... </dl>)
 \newenvironment{DoxyDescription}{%
index a9446d7..b245437 100644 (file)
       colorlinks=true,%
       linkcolor=blue,%
       citecolor=blue,%
-      unicode%
+      unicode,%
+      pdftitle=$projectname,%
+      pdfsubject=$projectbrief%
     }
 
 %%END PDF_HYPERLINKS
index f540c8a..ba73dd0 100644 (file)
       <xsd:element name="definition" minOccurs="0" />
       <xsd:element name="argsstring" minOccurs="0" />
       <xsd:element name="name" />
+      <xsd:element name="qualifiedname" minOccurs="0"/>
       <xsd:element name="read" minOccurs="0" />
       <xsd:element name="write" minOccurs="0" />
       <xsd:element name="bitfield" minOccurs="0" />
       <xsd:element name="superscript" type="docMarkupType" />
       <xsd:element name="center" type="docMarkupType" />
       <xsd:element name="small" type="docMarkupType" />
+      <xsd:element name="cite" type="docMarkupType" />
       <xsd:element name="del" type="docMarkupType" />
       <xsd:element name="ins" type="docMarkupType" />
+      <xsd:element name="details" type="docMarkupType" />
+      <xsd:element name="summary" type="docMarkupType" />
       <xsd:element name="htmlonly" type="docHtmlOnlyType" />
       <xsd:element name="manonly" type="xsd:string" />
       <xsd:element name="xmlonly" type="xsd:string" />
       <xsd:element name="latexonly" type="xsd:string" />
       <xsd:element name="docbookonly" type="xsd:string" />
       <xsd:element name="image" type="docImageType" />
-      <xsd:element name="dot" type="docImageType" />
-      <xsd:element name="msc" type="docImageType" />
-      <xsd:element name="plantuml" type="docImageType" />
+      <xsd:element name="dot" type="docDotMscType" />
+      <xsd:element name="msc" type="docDotMscType" />
+      <xsd:element name="plantuml" type="docPlantumlType" />
       <xsd:element name="anchor" type="docAnchorType" />
       <xsd:element name="formula" type="docFormulaType" />
       <xsd:element name="ref" type="docRefTextType" />
       <xsd:element name="preformatted" type="docMarkupType" />
       <xsd:element name="programlisting" type="listingType" />
       <xsd:element name="verbatim" type="xsd:string" />
+      <xsd:element name="javadocliteral" type="xsd:string" />
+      <xsd:element name="javadoccode" type="xsd:string" />
       <xsd:element name="indexentry" type="docIndexEntryType" />
       <xsd:element name="orderedlist" type="docListType" />
       <xsd:element name="itemizedlist" type="docListType" />
       <xsd:element name="variablelist" type="docVariableListType" />
       <xsd:element name="table" type="docTableType" />
       <xsd:element name="heading" type="docHeadingType" />
-      <xsd:element name="dotfile" type="docImageType" />
-      <xsd:element name="mscfile" type="docImageType" />
-      <xsd:element name="diafile" type="docImageType" />
+      <xsd:element name="dotfile" type="docImageFileType" />
+      <xsd:element name="mscfile" type="docImageFileType" />
+      <xsd:element name="diafile" type="docImageFileType" />
       <xsd:element name="toclist" type="docTocListType" />
       <xsd:element name="language" type="docLanguageType" />
       <xsd:element name="parameterlist" type="docParamListType" />
     <xsd:sequence>
       <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
     </xsd:sequence>
+    <xsd:attribute name="value" type="xsd:integer" use="optional"/>
   </xsd:complexType>
 
   <xsd:complexType name="docSimpleSectType">
 
   <xsd:complexType name="docCaptionType" mixed="true">
     <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <xsd:attribute name="id" type="xsd:string" /> 
   </xsd:complexType>
 
   <xsd:complexType name="docHeadingType" mixed="true">
     <xsd:attribute name="caption" type="xsd:string" use="optional"/>
   </xsd:complexType>
 
+  <xsd:complexType name="docDotMscType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <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="caption" type="xsd:string" use="optional"/>
+  </xsd:complexType>
+
+  <xsd:complexType name="docImageFileType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <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:complexType>
+
+  <xsd:complexType name="docPlantumlType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <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="caption" type="xsd:string" use="optional"/>
+    <xsd:attribute name="engine" type="DoxPlantumlEngine" use="optional"/>
+  </xsd:complexType>
+
   <xsd:complexType name="docTocItemType" mixed="true">
     <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
     <xsd:attribute name="id" type="xsd:string" /> 
       <xsd:enumeration value="latex" />
       <xsd:enumeration value="docbook" />
       <xsd:enumeration value="rtf" />
+      <xsd:enumeration value="xml" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxPlantumlEngine">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="uml"/>
+      <xsd:enumeration value="bpm"/>
+      <xsd:enumeration value="wire"/>
+      <xsd:enumeration value="dot"/>
+      <xsd:enumeration value="ditaa"/>
+      <xsd:enumeration value="salt"/>
+      <xsd:enumeration value="math"/>
+      <xsd:enumeration value="latex"/>
+      <xsd:enumeration value="gantt"/>
+      <xsd:enumeration value="mindmap"/>
+      <xsd:enumeration value="wbs"/>
+      <xsd:enumeration value="yaml"/>
+      <xsd:enumeration value="creole"/>
+      <xsd:enumeration value="json"/>
+      <xsd:enumeration value="flow"/>
+      <xsd:enumeration value="board"/>
+      <xsd:enumeration value="git"/>
     </xsd:restriction>
   </xsd:simpleType>
 
index 71b9851..fbfc2c1 100755 (executable)
   </xsd:simpleType>
 
 </xsd:schema>
-
-<!--
-<?xml version='1.0' encoding='UTF-8' standalone='no'?>
-<doxyfile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="doxyfile.xsd" version="1.9.2" xml:lang="en-US">
-  <option  id='DOXYFILE_ENCODING' default='yes' type='string'><![CDATA[UTF-8]]></option>
-<value><![CDATA[d:/Programs/CGAL/cgal_fork/AABB_tree/doc/AABB_tree/]]></value>
--->
-
index b629592..e6a4b35 100644 (file)
@@ -8,6 +8,7 @@
         <definition>void Bug::foo</definition>
         <argsstring>()</argsstring>
         <name>foo</name>
+        <qualifiedname>Bug::foo</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
index 0c08227..0847cd7 100644 (file)
@@ -8,6 +8,7 @@
         <definition>void Deprecated::deprecated</definition>
         <argsstring>()</argsstring>
         <name>deprecated</name>
+        <qualifiedname>Deprecated::deprecated</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
index bd09607..0daed60 100644 (file)
@@ -8,6 +8,7 @@
         <definition>void Reminder::reminder</definition>
         <argsstring>()</argsstring>
         <name>reminder</name>
+        <qualifiedname>Reminder::reminder</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
index 79a9ca7..0130cd4 100644 (file)
@@ -8,6 +8,7 @@
         <definition>void Test::test</definition>
         <argsstring>()</argsstring>
         <name>test</name>
+        <qualifiedname>Test::test</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
index 00e55d2..31718b5 100644 (file)
@@ -8,6 +8,7 @@
         <definition>void Todo::todo</definition>
         <argsstring>()</argsstring>
         <name>todo</name>
+        <qualifiedname>Todo::todo</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
index bfde98e..11f3940 100644 (file)
@@ -8,6 +8,7 @@
         <definition>id Integer(Arithmetic)::add:</definition>
         <argsstring>(Integer *addend)</argsstring>
         <name>add:</name>
+        <qualifiedname>-[Integer(Arithmetic) add:]</qualifiedname>
         <param>
           <type><ref refid="interface_integer" kindref="compound">Integer</ref> *</type>
           <declname>addend</declname>
@@ -26,6 +27,7 @@
         <definition>id Integer(Arithmetic)::sub:</definition>
         <argsstring>(Integer *subtrahend)</argsstring>
         <name>sub:</name>
+        <qualifiedname>-[Integer(Arithmetic) sub:]</qualifiedname>
         <param>
           <type><ref refid="interface_integer" kindref="compound">Integer</ref> *</type>
           <declname>subtrahend</declname>
index 786bc2a..8c1b70b 100644 (file)
@@ -9,6 +9,7 @@
         <definition>int Integer::integer</definition>
         <argsstring/>
         <name>integer</name>
+        <qualifiedname>Integer::integer</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
@@ -25,6 +26,7 @@
         <definition>int Integer::integer</definition>
         <argsstring>()</argsstring>
         <name>integer</name>
+        <qualifiedname>-[Integer integer]</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
@@ -39,6 +41,7 @@
         <definition>id Integer::integer:</definition>
         <argsstring>(int _integer)</argsstring>
         <name>integer:</name>
+        <qualifiedname>-[Integer integer:]</qualifiedname>
         <param>
           <type>int</type>
           <declname>_integer</declname>
diff --git a/testing/019/group___a.xml b/testing/019/group___a.xml
new file mode 100644 (file)
index 0000000..0436412
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="" xml:lang="en-US">
+  <compounddef id="group___a" kind="group">
+    <compoundname>A</compoundname>
+    <title>A</title>
+    <innergroup refid="group___b">B</innergroup>
+    <innergroup refid="group___c">C</innergroup>
+    <innergroup refid="group___d">D</innergroup>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+  </compounddef>
+</doxygen>
diff --git a/testing/019/group___b.xml b/testing/019/group___b.xml
new file mode 100644 (file)
index 0000000..4ab6068
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="" xml:lang="en-US">
+  <compounddef id="group___b" kind="group">
+    <compoundname>B</compoundname>
+    <title>B</title>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+  </compounddef>
+</doxygen>
diff --git a/testing/019/group___c.xml b/testing/019/group___c.xml
new file mode 100644 (file)
index 0000000..3bf2f02
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="" xml:lang="en-US">
+  <compounddef id="group___c" kind="group">
+    <compoundname>C</compoundname>
+    <title>C</title>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+  </compounddef>
+</doxygen>
diff --git a/testing/019/group___d.xml b/testing/019/group___d.xml
new file mode 100644 (file)
index 0000000..c623e2a
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="" xml:lang="en-US">
+  <compounddef id="group___d" kind="group">
+    <compoundname>D</compoundname>
+    <title>D</title>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+  </compounddef>
+</doxygen>
index 5754a4e..9f07e56 100644 (file)
@@ -16,7 +16,7 @@
         </detaileddescription>
         <inbodydescription>
         </inbodydescription>
-        <location file="019_defgroup.c" line="13" column="6" declfile="019_defgroup.c" declline="13" declcolumn="6"/>
+        <location file="019_defgroup.c" line="17" column="6" declfile="019_defgroup.c" declline="17" declcolumn="6"/>
       </memberdef>
     </sectiondef>
     <briefdescription>
index 2a9a98e..eb41e3e 100644 (file)
@@ -17,7 +17,7 @@
         </detaileddescription>
         <inbodydescription>
         </inbodydescription>
-        <location file="019_defgroup.c" line="23" column="6" declfile="019_defgroup.c" declline="23" declcolumn="6"/>
+        <location file="019_defgroup.c" line="27" column="6" declfile="019_defgroup.c" declline="27" declcolumn="6"/>
       </memberdef>
     </sectiondef>
     <briefdescription>
index f65be47..806249c 100644 (file)
@@ -16,7 +16,7 @@
         </detaileddescription>
         <inbodydescription>
         </inbodydescription>
-        <location file="019_defgroup.c" line="36" column="6" declfile="019_defgroup.c" declline="36" declcolumn="6"/>
+        <location file="019_defgroup.c" line="40" column="6" declfile="019_defgroup.c" declline="40" declcolumn="6"/>
       </memberdef>
       <memberdef kind="function" id="group__g3_1gaf32d23522a5d9c3e7fed3dd5710001f7" prot="public" static="no" const="no" explicit="no" inline="no" virt="non-virtual">
         <type>void</type>
@@ -30,7 +30,7 @@
         </detaileddescription>
         <inbodydescription>
         </inbodydescription>
-        <location file="019_defgroup.c" line="45" column="6" declfile="019_defgroup.c" declline="45" declcolumn="6"/>
+        <location file="019_defgroup.c" line="49" column="6" declfile="019_defgroup.c" declline="49" declcolumn="6"/>
       </memberdef>
     </sectiondef>
     <briefdescription>
index d7e440e..793805d 100644 (file)
@@ -2,6 +2,10 @@
 // check: group__g1.xml
 // check: group__g2.xml
 // check: group__g3.xml
+// check: group___a.xml
+// check: group___b.xml
+// check: group___c.xml
+// check: group___d.xml
 
 /** \defgroup g1 First Group
  *  Text for first group.
@@ -46,3 +50,30 @@ void func_g3_add();
 
 /** \} */
 
+/**
+  @defgroup A A
+  @{
+ */
+
+/** @defgroup B B
+   @{
+ */
+
+/// \}
+
+/** @defgroup C C
+   @{
+ */
+
+/** @} */
+
+/**
+  @defgroup D D
+  @{
+ */
+
+/// @}
+
+/**
+@}
+*/
index 473482a..2626d68 100644 (file)
@@ -6,7 +6,7 @@
     <briefdescription>
     </briefdescription>
     <detaileddescription>
-      <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>
+      <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>
     <location file="021_dontinclude.cpp"/>
   </compounddef>
index 026ae8c..1fb57ed 100644 (file)
@@ -6,20 +6,20 @@
     <briefdescription>
     </briefdescription>
     <detaileddescription>
-      <para>Unconditional (start) Enabled (if). Enabled (else). Unconditional (middle) Enabled (else). Unconditional (end)</para>
+      <para>Unconditional (start)  Enabled (if).  Enabled (else).   Unconditional (middle)  Enabled (else).  Unconditional (end)</para>
       <sect1 id="index_1autotoc_md0">
         <title>with spaces</title>
-        <para>test1 test3 test4.</para>
-        <para>test1 test2 test4.</para>
-        <para>test1 test2 test3.</para>
-        <para>test1 test3.</para>
+        <para>test1  test3  test4.</para>
+        <para>test1  test2  test4.</para>
+        <para>test1  test2  test3.</para>
+        <para>test1  test3.</para>
       </sect1>
       <sect1 id="index_1autotoc_md1">
         <title>without spaces</title>
-        <para>test1test3test4.</para>
-        <para>test1test2test4.</para>
-        <para>test1test2test3.</para>
-        <para>test1test3. </para>
+        <para>test1 test3 test4.</para>
+        <para>test1 test2 test4.</para>
+        <para>test1 test2 test3.</para>
+        <para>test1 test3. </para>
       </sect1>
     </detaileddescription>
     <location file="024_if.dox"/>
index f181488..261cdde 100644 (file)
@@ -8,6 +8,7 @@
         <definition>void Test::example</definition>
         <argsstring>()</argsstring>
         <name>example</name>
+        <qualifiedname>Test::example</qualifiedname>
         <briefdescription>
           <para>An example member function. </para>
         </briefdescription>
index 872746e..5f1f551 100644 (file)
@@ -13,6 +13,7 @@
         <definition>int Test&lt; T &gt;::example</definition>
         <argsstring>(int p1, int p2)</argsstring>
         <name>example</name>
+        <qualifiedname>Test::example</qualifiedname>
         <param>
           <type>int</type>
           <declname>p1</declname>
index a2d384d..411d5e1 100644 (file)
@@ -11,6 +11,7 @@
         <definition>Vehicle Car::base</definition>
         <argsstring/>
         <name>base</name>
+        <qualifiedname>Car::base</qualifiedname>
         <briefdescription>
           <para>Base class. </para>
         </briefdescription>
index 36866ac..2f74e1d 100644 (file)
@@ -9,6 +9,7 @@
         <definition>int Object::ref</definition>
         <argsstring/>
         <name>ref</name>
+        <qualifiedname>Object::ref</qualifiedname>
         <briefdescription>
           <para>Reference count. </para>
         </briefdescription>
         <location file="027_extends.c" line="21" column="7" bodyfile="027_extends.c" bodystart="21" bodyend="-1"/>
       </memberdef>
     </sectiondef>
-    <sectiondef kind="public-func">
-      <memberdef kind="function" id="struct_object_1a71225073d06a793b9a6ea9263ed37b12" prot="public" static="no" const="no" explicit="no" inline="no" virt="non-virtual">
+    <sectiondef kind="public-static-func">
+      <memberdef kind="function" id="struct_object_1a71225073d06a793b9a6ea9263ed37b12" prot="public" static="yes" const="no" explicit="no" inline="no" virt="non-virtual">
         <type><ref refid="struct_object" kindref="compound">Object</ref> *</type>
         <definition>static Object * objRef</definition>
         <argsstring>(Object *obj)</argsstring>
         <name>objRef</name>
+        <qualifiedname>Object::objRef</qualifiedname>
         <param>
           <type><ref refid="struct_object" kindref="compound">Object</ref> *</type>
           <declname>obj</declname>
         </inbodydescription>
         <location file="027_extends.c" line="29" column="16" declfile="027_extends.c" declline="29" declcolumn="16"/>
       </memberdef>
-      <memberdef kind="function" id="struct_object_1a924ee0cecc906d148022b3f0d6325cfb" prot="public" static="no" const="no" explicit="no" inline="no" virt="non-virtual">
+      <memberdef kind="function" id="struct_object_1a924ee0cecc906d148022b3f0d6325cfb" prot="public" static="yes" const="no" explicit="no" inline="no" virt="non-virtual">
         <type><ref refid="struct_object" kindref="compound">Object</ref> *</type>
         <definition>static Object * objUnref</definition>
         <argsstring>(Object *obj)</argsstring>
         <name>objUnref</name>
+        <qualifiedname>Object::objUnref</qualifiedname>
         <param>
           <type><ref refid="struct_object" kindref="compound">Object</ref> *</type>
           <declname>obj</declname>
index 2e10c7a..efecafd 100644 (file)
@@ -11,6 +11,7 @@
         <definition>Vehicle Truck::base</definition>
         <argsstring/>
         <name>base</name>
+        <qualifiedname>Truck::base</qualifiedname>
         <briefdescription>
           <para>Base class. </para>
         </briefdescription>
index 9f9e27b..1efdcd2 100644 (file)
@@ -13,6 +13,7 @@
         <definition>Object Vehicle::base</definition>
         <argsstring/>
         <name>base</name>
+        <qualifiedname>Vehicle::base</qualifiedname>
         <briefdescription>
           <para>Base class. </para>
         </briefdescription>
@@ -29,6 +30,7 @@
         <definition>void vehicleStart</definition>
         <argsstring>(Vehicle *obj)</argsstring>
         <name>vehicleStart</name>
+        <qualifiedname>Vehicle::vehicleStart</qualifiedname>
         <param>
           <type><ref refid="struct_vehicle" kindref="compound">Vehicle</ref> *</type>
           <declname>obj</declname>
@@ -47,6 +49,7 @@
         <definition>void vehicleStop</definition>
         <argsstring>(Vehicle *obj)</argsstring>
         <name>vehicleStop</name>
+        <qualifiedname>Vehicle::vehicleStop</qualifiedname>
         <param>
           <type><ref refid="struct_vehicle" kindref="compound">Vehicle</ref> *</type>
           <declname>obj</declname>
index 0690560..f50d62e 100644 (file)
@@ -23,7 +23,7 @@
 <image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.png"/>
 </para>
       <para>Inline SVG image with caption:<linebreak/>
-This image is inline <image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.svg" inline="yes">MIT license</image>
+This image is inline<image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.svg" inline="yes">MIT license</image>
  within the text.</para>
       <para>Inline PNG image with caption:<linebreak/>
 This image is inline <image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.png" inline="yes">MIT license</image>
index 15f3611..7f5605a 100644 (file)
@@ -8,6 +8,7 @@
         <definition>void Receiver::Command</definition>
         <argsstring>(int commandId)</argsstring>
         <name>Command</name>
+        <qualifiedname>Receiver::Command</qualifiedname>
         <param>
           <type>int</type>
           <declname>commandId</declname>
index 91dd3d6..7b32a8c 100644 (file)
@@ -8,6 +8,7 @@
         <definition>void Sender::Ack</definition>
         <argsstring>(bool ok)</argsstring>
         <name>Ack</name>
+        <qualifiedname>Sender::Ack</qualifiedname>
         <param>
           <type>bool</type>
           <declname>ok</declname>
index 8dd6574..96aa46e 100644 (file)
@@ -9,6 +9,7 @@
         <definition>void Test::foo</definition>
         <argsstring>()</argsstring>
         <name>foo</name>
+        <qualifiedname>Test::foo</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
@@ -23,6 +24,7 @@
         <definition>void Test::bar</definition>
         <argsstring>()</argsstring>
         <name>bar</name>
+        <qualifiedname>Test::bar</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
@@ -39,6 +41,7 @@
         <definition>void Test::ungrouped</definition>
         <argsstring>()</argsstring>
         <name>ungrouped</name>
+        <qualifiedname>Test::ungrouped</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
index c4dda88..c5ab4c8 100644 (file)
@@ -8,6 +8,7 @@
         <definition>void Test::drawRect</definition>
         <argsstring>(int, int, int, int)</argsstring>
         <name>drawRect</name>
+        <qualifiedname>Test::drawRect</qualifiedname>
         <param>
           <type>int</type>
           <defname>x</defname>
@@ -38,6 +39,7 @@
         <definition>void Test::drawRect</definition>
         <argsstring>(const Rect &amp;r)</argsstring>
         <name>drawRect</name>
+        <qualifiedname>Test::drawRect</qualifiedname>
         <param>
           <type>const Rect &amp;</type>
           <declname>r</declname>
@@ -56,6 +58,7 @@
         <definition>void Test::drawRect</definition>
         <argsstring>(const Point &amp;topLeft, const Point &amp;bottomRight)</argsstring>
         <name>drawRect</name>
+        <qualifiedname>Test::drawRect</qualifiedname>
         <param>
           <type>const Point &amp;</type>
           <declname>topLeft</declname>
index d1a65bd..2ef3414 100644 (file)
@@ -36,7 +36,6 @@
       <para>Page brief description. </para>
     </briefdescription>
     <detaileddescription>
-      <para>Page brief description.</para>
       <para>Text at page level. See <ref refid="mypage_1mysect" kindref="member">Section Title.</ref> for more. </para>
       <sect1 id="mypage_1mysect">
         <title>Section Title.</title>
index 4aa6bfd..73f0138 100644 (file)
@@ -9,6 +9,7 @@
         <definition>int S::pub1</definition>
         <argsstring/>
         <name>pub1</name>
+        <qualifiedname>S::pub1</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
@@ -23,6 +24,7 @@
         <definition>int S::pub2</definition>
         <argsstring/>
         <name>pub2</name>
+        <qualifiedname>S::pub2</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
@@ -39,6 +41,7 @@
         <definition>int S::pro1</definition>
         <argsstring/>
         <name>pro1</name>
+        <qualifiedname>S::pro1</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
@@ -53,6 +56,7 @@
         <definition>int S::pro2</definition>
         <argsstring/>
         <name>pro2</name>
+        <qualifiedname>S::pro2</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
@@ -69,6 +73,7 @@
         <definition>int S::pri1</definition>
         <argsstring/>
         <name>pri1</name>
+        <qualifiedname>S::pri1</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
@@ -83,6 +88,7 @@
         <definition>int S::pri2</definition>
         <argsstring/>
         <name>pri2</name>
+        <qualifiedname>S::pri2</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
index 453b463..33a1932 100644 (file)
@@ -8,6 +8,7 @@
         <definition>void Test::method</definition>
         <argsstring>()</argsstring>
         <name>method</name>
+        <qualifiedname>Test::method</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
@@ -24,6 +25,7 @@
         <definition>void function</definition>
         <argsstring>()</argsstring>
         <name>function</name>
+        <qualifiedname>Test::function</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
@@ -45,6 +47,7 @@
         <definition>void another</definition>
         <argsstring>()</argsstring>
         <name>another</name>
+        <qualifiedname>Test::another</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
index 2b78363..29d22c2 100644 (file)
@@ -6,7 +6,7 @@
     <briefdescription>
     </briefdescription>
     <detaileddescription>
-      <para>A bubble sort algorithm First get the inputs <programlisting filename="snippet_test.cpp"><codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="keywordflow">for</highlight><highlight class="normal">(i=0<sp/>;<sp/>i&lt;n<sp/>;<sp/>i++)</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>{</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/>printf(</highlight><highlight class="stringliteral">"<sp/>Array[%d]<sp/>=<sp/>"</highlight><highlight class="normal">,i);</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/>scanf(</highlight><highlight class="stringliteral">"%d"</highlight><highlight class="normal">,&amp;arr[i]);</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>}</highlight></codeline></programlisting>Then do the bubbling <programlisting filename="snippet_test.cpp"><codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="keywordflow">for</highlight><highlight class="normal">(i=0<sp/>;<sp/>i&lt;n<sp/>;<sp/>i++)</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>{</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/></highlight><highlight class="keywordflow">for</highlight><highlight class="normal">(j=0<sp/>;<sp/>j&lt;n-i-1<sp/>;<sp/>j++)</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/>{</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/></highlight><highlight class="keywordflow">if</highlight><highlight class="normal">(arr[j]&gt;arr[j+1])<sp/></highlight><highlight class="comment">//Swapping<sp/>Condition<sp/>is<sp/>Checked</highlight><highlight class="normal"/></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/>{</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/>temp=arr[j];</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/>arr[j]=arr[j+1];</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/>arr[j+1]=temp;</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/>}</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/>}</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>}</highlight></codeline></programlisting>Then write the result <programlisting filename="snippet_test.cpp"><codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="keywordflow">for</highlight><highlight class="normal">(i=0<sp/>;<sp/>i&lt;n<sp/>;<sp/>i++)</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>{</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/>printf(</highlight><highlight class="stringliteral">"<sp/>%4d"</highlight><highlight class="normal">,arr[i]);</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>}</highlight></codeline></programlisting></para>
+      <para>A bubble sort algorithm First get the inputs <programlisting filename="snippet_test.cpp"><codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="keywordflow">for</highlight><highlight class="normal">(i=0<sp/>;<sp/>i&lt;n<sp/>;<sp/>i++)</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>{</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/>printf(</highlight><highlight class="stringliteral">"<sp/>Array[%d]<sp/>=<sp/>"</highlight><highlight class="normal">,i);</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/>scanf(</highlight><highlight class="stringliteral">"%d"</highlight><highlight class="normal">,&amp;arr[i]);</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>}</highlight></codeline></programlisting> Then do the bubbling <programlisting filename="snippet_test.cpp"><codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="keywordflow">for</highlight><highlight class="normal">(i=0<sp/>;<sp/>i&lt;n<sp/>;<sp/>i++)</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>{</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/></highlight><highlight class="keywordflow">for</highlight><highlight class="normal">(j=0<sp/>;<sp/>j&lt;n-i-1<sp/>;<sp/>j++)</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/>{</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/></highlight><highlight class="keywordflow">if</highlight><highlight class="normal">(arr[j]&gt;arr[j+1])<sp/></highlight><highlight class="comment">//Swapping<sp/>Condition<sp/>is<sp/>Checked</highlight><highlight class="normal"/></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/>{</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/>temp=arr[j];</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/>arr[j]=arr[j+1];</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/><sp/><sp/>arr[j+1]=temp;</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/><sp/><sp/>}</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/>}</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>}</highlight></codeline></programlisting> Then write the result <programlisting filename="snippet_test.cpp"><codeline><highlight class="normal"><sp/><sp/></highlight><highlight class="keywordflow">for</highlight><highlight class="normal">(i=0<sp/>;<sp/>i&lt;n<sp/>;<sp/>i++)</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>{</highlight></codeline><codeline><highlight class="normal"><sp/><sp/><sp/><sp/>printf(</highlight><highlight class="stringliteral">"<sp/>%4d"</highlight><highlight class="normal">,arr[i]);</highlight></codeline><codeline><highlight class="normal"><sp/><sp/>}</highlight></codeline></programlisting> </para>
     </detaileddescription>
     <location file="049_snippet.cpp"/>
   </compounddef>
index 8423c35..b842141 100644 (file)
@@ -23,7 +23,7 @@
           <para>
             <ulink url="http://example.com/last-line">Upper-cased reference link on last line</ulink>
           </para>
-          <para>Dash - NDash <ndash/> MDash <mdash/> EDash - ENDash -- EMDash --- E3Dash --- </para>
+          <para>Dash - NDash <ndash/> MDash <mdash/> EDash - ENDash -- EMDash --- E3Dash ---</para>
         </sect2>
         <sect2 id="md_055_markdown_1autotoc_md3">
           <title>Markdown in HTML</title>
index 5321ad7..79ecb0a 100644 (file)
@@ -12,6 +12,7 @@
         <definition>void library::v2::func</definition>
         <argsstring>()</argsstring>
         <name>func</name>
+        <qualifiedname>library::v2::func</qualifiedname>
         <briefdescription>
           <para>a method </para>
         </briefdescription>
index 9a01e02..bd64a2a 100644 (file)
@@ -10,6 +10,7 @@
         <definition>void library::v1::func</definition>
         <argsstring>()</argsstring>
         <name>func</name>
+        <qualifiedname>library::v1::func</qualifiedname>
         <briefdescription>
           <para>a method </para>
         </briefdescription>
index fd848fd..3dd6a39 100644 (file)
@@ -10,6 +10,7 @@
         <definition>void library::v2::func</definition>
         <argsstring>()</argsstring>
         <name>func</name>
+        <qualifiedname>library::v2::func</qualifiedname>
         <briefdescription>
           <para>a method </para>
         </briefdescription>
index edf6de5..a14c2af 100644 (file)
@@ -6,6 +6,7 @@
       <memberdef kind="enum" id="class_class_1a2f3072754ba509a9e86403439b18fddb" prot="public" static="no" strong="yes">
         <type/>
         <name>Enum1</name>
+        <qualifiedname>Class::Enum1</qualifiedname>
         <enumvalue id="class_class_1a2f3072754ba509a9e86403439b18fddbac5836008c1649301e29351a55db8f65c" prot="public">
           <name>Flag</name>
           <briefdescription>
@@ -26,6 +27,7 @@
       <memberdef kind="enum" id="class_class_1af09ec8b7238c8a302c251b1cfe1de13d" prot="public" static="no" strong="yes">
         <type/>
         <name>Enum2</name>
+        <qualifiedname>Class::Enum2</qualifiedname>
         <enumvalue id="class_class_1af09ec8b7238c8a302c251b1cfe1de13dac5836008c1649301e29351a55db8f65c" prot="public">
           <name>Flag</name>
           <briefdescription>
index 4706061..3578d85 100644 (file)
@@ -6,6 +6,7 @@
       <memberdef kind="enum" id="classns2_1_1_class_1ab3fe6da2ca4a96a226618492312b1761" prot="public" static="no" strong="yes">
         <type/>
         <name>Enum1</name>
+        <qualifiedname>ns2::Class::Enum1</qualifiedname>
         <enumvalue id="classns2_1_1_class_1ab3fe6da2ca4a96a226618492312b1761ac5836008c1649301e29351a55db8f65c" prot="public">
           <name>Flag</name>
           <briefdescription>
@@ -26,6 +27,7 @@
       <memberdef kind="enum" id="classns2_1_1_class_1ae96c8ec290b0bdb3b718ccd891450b5d" prot="public" static="no" strong="yes">
         <type/>
         <name>Enum2</name>
+        <qualifiedname>ns2::Class::Enum2</qualifiedname>
         <enumvalue id="classns2_1_1_class_1ae96c8ec290b0bdb3b718ccd891450b5dac5836008c1649301e29351a55db8f65c" prot="public">
           <name>Flag</name>
           <briefdescription>
index f3ae467..df13792 100644 (file)
@@ -6,6 +6,7 @@
       <memberdef kind="enum" id="classns_1_1_class_1a00bce7c1691da19e4e1c2e770c9297e3" prot="public" static="no" strong="yes">
         <type/>
         <name>Enum1</name>
+        <qualifiedname>ns::Class::Enum1</qualifiedname>
         <enumvalue id="classns_1_1_class_1a00bce7c1691da19e4e1c2e770c9297e3ac5836008c1649301e29351a55db8f65c" prot="public">
           <name>Flag</name>
           <briefdescription>
@@ -26,6 +27,7 @@
       <memberdef kind="enum" id="classns_1_1_class_1a2f5b74a27a12bfc86e653a13178317e4" prot="public" static="no" strong="yes">
         <type/>
         <name>Enum2</name>
+        <qualifiedname>ns::Class::Enum2</qualifiedname>
         <enumvalue id="classns_1_1_class_1a2f5b74a27a12bfc86e653a13178317e4ac5836008c1649301e29351a55db8f65c" prot="public">
           <name>Flag</name>
           <briefdescription>
diff --git a/testing/059/struct_n_1_1allocator__traits.xml b/testing/059/struct_n_1_1allocator__traits.xml
new file mode 100644 (file)
index 0000000..f2227cf
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="" xml:lang="en-US">
+  <compounddef id="struct_n_1_1allocator__traits" kind="struct" language="C++" prot="public">
+    <compoundname>N::allocator_traits</compoundname>
+    <templateparamlist>
+      <param>
+        <type>typename _Alloc</type>
+      </param>
+    </templateparamlist>
+    <sectiondef kind="public-type">
+      <memberdef kind="typedef" id="struct_n_1_1allocator__traits_1a764c5cc2bd9edc0cfa83282a3f5a75f8" prot="public" static="no">
+        <type>typename _Ptr&lt; __c_pointer, const value_type &gt;::type</type>
+        <definition>using N::allocator_traits&lt; _Alloc &gt;::const_pointer =  typename _Ptr&lt;__c_pointer, const value_type&gt;::type</definition>
+        <argsstring/>
+        <name>const_pointer</name>
+        <qualifiedname>N::allocator_traits::const_pointer</qualifiedname>
+        <briefdescription>
+          <para>The allocator's const pointer type. </para>
+        </briefdescription>
+        <detaileddescription>
+          <para><computeroutput>Alloc::const_pointer</computeroutput> if that type exists, otherwise <computeroutput>pointer_traits&lt;pointer&gt;::rebind&lt;const value_type&gt;</computeroutput>. </para>
+        </detaileddescription>
+        <inbodydescription>
+        </inbodydescription>
+        <location file="059_template.cpp" line="18" column="5" bodyfile="059_template.cpp" bodystart="18" bodyend="-1"/>
+      </memberdef>
+    </sectiondef>
+    <briefdescription>
+      <para>Uniform interface to all allocator types. </para>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <location file="059_template.cpp" line="8" column="13" bodyfile="059_template.cpp" bodystart="9" bodyend="19"/>
+    <listofallmembers>
+      <member refid="struct_n_1_1allocator__traits_1a764c5cc2bd9edc0cfa83282a3f5a75f8" prot="public" virt="non-virtual">
+        <scope>N::allocator_traits</scope>
+        <name>const_pointer</name>
+      </member>
+    </listofallmembers>
+  </compounddef>
+</doxygen>
diff --git a/testing/059_template.cpp b/testing/059_template.cpp
new file mode 100644 (file)
index 0000000..bea31ab
--- /dev/null
@@ -0,0 +1,20 @@
+// objective: test if A<B>::C within backticks is properly handled
+// check: struct_n_1_1allocator__traits.xml
+namespace N
+{
+  /**
+   * @brief  Uniform interface to all allocator types.
+   */
+  template<typename _Alloc> struct allocator_traits
+  {
+    /**
+     * @brief   The allocator's const pointer type.
+     *
+     *
+     * `Alloc::const_pointer` if that type exists, otherwise
+     * `pointer_traits<pointer>::rebind<const value_type>`.
+     *
+    */
+    using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
+  };
+}
index 9678cba..2ed5be1 100644 (file)
@@ -8,6 +8,7 @@
         <definition>Foo::operator int</definition>
         <argsstring>()</argsstring>
         <name>operator int</name>
+        <qualifiedname>Foo::operator int</qualifiedname>
         <briefdescription>
           <para>Conversion to int. </para>
         </briefdescription>
@@ -22,6 +23,7 @@
         <definition>Foo::operator int</definition>
         <argsstring>() const</argsstring>
         <name>operator int</name>
+        <qualifiedname>Foo::operator int</qualifiedname>
         <briefdescription>
           <para>Conversion to int const. </para>
         </briefdescription>
index 13ab56c..2a37c7e 100644 (file)
@@ -8,6 +8,7 @@
         <definition>int Class1.Property1</definition>
         <argsstring/>
         <name>Property1</name>
+        <qualifiedname>Class1.Property1</qualifiedname>
         <initializer>= 1</initializer>
         <briefdescription>
           <para>Documentation of first property. </para>
@@ -23,6 +24,7 @@
         <definition>string Class1.Property2</definition>
         <argsstring/>
         <name>Property2</name>
+        <qualifiedname>Class1.Property2</qualifiedname>
         <briefdescription>
           <para>Documentation of second property. </para>
         </briefdescription>
index fbe2c7a..72716cf 100644 (file)
@@ -6,6 +6,7 @@
       <memberdef kind="enum" id="namespace_a_namespace_1_1_0d0_1a96ab6574751fdf6a53ceec8a3896c45d" prot="public" static="no" strong="yes">
         <type/>
         <name>Boolean</name>
+        <qualifiedname>ANamespace::@0::Boolean</qualifiedname>
         <enumvalue id="namespace_a_namespace_1_1_0d0_1a96ab6574751fdf6a53ceec8a3896c45daf8320b26d30ab433c5a54546d21f414c" prot="public">
           <name>False</name>
           <briefdescription>
index f63fea5..a3e6e45 100644 (file)
@@ -8,6 +8,7 @@
         <definition>int ns::operator""_op</definition>
         <argsstring>(unsigned long long)</argsstring>
         <name>operator""_op</name>
+        <qualifiedname>ns::operator""_op</qualifiedname>
         <param>
           <type>unsigned long long</type>
         </param>
@@ -25,6 +26,7 @@
         <definition>int ns::operator""_oq</definition>
         <argsstring>(unsigned long long)</argsstring>
         <name>operator""_oq</name>
+        <qualifiedname>ns::operator""_oq</qualifiedname>
         <param>
           <type>unsigned long long</type>
         </param>
@@ -42,6 +44,7 @@
         <definition>void ns::foo</definition>
         <argsstring>(std::initializer_list&lt; int * &gt;)</argsstring>
         <name>foo</name>
+        <qualifiedname>ns::foo</qualifiedname>
         <param>
           <type>std::initializer_list&lt; int * &gt;</type>
         </param>
index 3c40407..82f5d1f 100644 (file)
@@ -8,6 +8,7 @@
         <definition>Foo::Foo</definition>
         <argsstring>()</argsstring>
         <name>Foo</name>
+        <qualifiedname>Foo::Foo</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
@@ -22,6 +23,7 @@
         <definition>Foo &amp; Foo::operator&lt;&lt;</definition>
         <argsstring>(int i)</argsstring>
         <name>operator&lt;&lt;</name>
+        <qualifiedname>Foo::operator&lt;&lt;</qualifiedname>
         <param>
           <type>int</type>
           <declname>i</declname>
@@ -40,6 +42,7 @@
         <definition>const Foo &amp; Foo::operator&lt;&lt;</definition>
         <argsstring>(int i) const</argsstring>
         <name>operator&lt;&lt;</name>
+        <qualifiedname>Foo::operator&lt;&lt;</qualifiedname>
         <param>
           <type>int</type>
           <declname>i</declname>
@@ -58,6 +61,7 @@
         <definition>int Foo::operator()</definition>
         <argsstring>(int i)</argsstring>
         <name>operator()</name>
+        <qualifiedname>Foo::operator()</qualifiedname>
         <param>
           <type>int</type>
           <declname>i</declname>
@@ -76,6 +80,7 @@
         <definition>int Foo::operator()</definition>
         <argsstring>(int i) const</argsstring>
         <name>operator()</name>
+        <qualifiedname>Foo::operator()</qualifiedname>
         <param>
           <type>int</type>
           <declname>i</declname>
@@ -94,6 +99,7 @@
         <definition>Foo &amp; Foo::operator&amp;=</definition>
         <argsstring>(const Foo &amp;rhs)</argsstring>
         <name>operator&amp;=</name>
+        <qualifiedname>Foo::operator&amp;=</qualifiedname>
         <param>
           <type>const <ref refid="struct_foo" kindref="compound">Foo</ref> &amp;</type>
           <declname>rhs</declname>
         <definition>const Foo &amp; Foo::operator&amp;=</definition>
         <argsstring>(const Foo &amp;rhs) const</argsstring>
         <name>operator&amp;=</name>
+        <qualifiedname>Foo::operator&amp;=</qualifiedname>
         <param>
           <type>const <ref refid="struct_foo" kindref="compound">Foo</ref> &amp;</type>
           <declname>rhs</declname>
         <definition>int * Foo::operator-&gt;*</definition>
         <argsstring>(int *p)</argsstring>
         <name>operator-&gt;*</name>
+        <qualifiedname>Foo::operator-&gt;*</qualifiedname>
         <param>
           <type>int *</type>
           <declname>p</declname>
         <definition>Foo Foo::fun</definition>
         <argsstring>() const</argsstring>
         <name>fun</name>
+        <qualifiedname>Foo::fun</qualifiedname>
         <briefdescription>
           <para>Fun with itself. </para>
         </briefdescription>
         <definition>static Foo Foo::fun</definition>
         <argsstring>(Foo a, Foo b)</argsstring>
         <name>fun</name>
+        <qualifiedname>Foo::fun</qualifiedname>
         <param>
           <type>
             <ref refid="struct_foo" kindref="compound">Foo</ref>
index dc947e9..64c0b09 100644 (file)
@@ -8,6 +8,7 @@
         <definition>void Foo::foo</definition>
         <argsstring>(float value)</argsstring>
         <name>foo</name>
+        <qualifiedname>Foo::foo</qualifiedname>
         <param>
           <type>float</type>
           <declname>value</declname>
@@ -26,6 +27,7 @@
         <definition>void Foo::foo</definition>
         <argsstring>(unsigned value)</argsstring>
         <name>foo</name>
+        <qualifiedname>Foo::foo</qualifiedname>
         <param>
           <type>unsigned</type>
           <declname>value</declname>
@@ -44,6 +46,7 @@
         <definition>void Foo::foo</definition>
         <argsstring>(unsigned long)</argsstring>
         <name>foo</name>
+        <qualifiedname>Foo::foo</qualifiedname>
         <param>
           <type>unsigned long</type>
         </param>
@@ -61,6 +64,7 @@
         <definition>void Foo::foo</definition>
         <argsstring>(signed long)</argsstring>
         <name>foo</name>
+        <qualifiedname>Foo::foo</qualifiedname>
         <param>
           <type>signed long</type>
         </param>
@@ -78,6 +82,7 @@
         <definition>void Foo::foo</definition>
         <argsstring>(const struct Foo)</argsstring>
         <name>foo</name>
+        <qualifiedname>Foo::foo</qualifiedname>
         <param>
           <type>const struct <ref refid="struct_foo" kindref="compound">Foo</ref></type>
         </param>
         <definition>void Foo::foo</definition>
         <argsstring>(const char *const, const double param2)</argsstring>
         <name>foo</name>
+        <qualifiedname>Foo::foo</qualifiedname>
         <param>
           <type>const char * const</type>
         </param>
index 3b6fd6c..d4829b9 100644 (file)
  <emoji name="8ball" unicode="&amp;#x1f3b1;"/> <emoji name="8ball" unicode="&amp;#x1f3b1;"/> from "8ball"<linebreak/>
  <emoji name="a" unicode="&amp;#x1f170;"/> <emoji name="a" unicode="&amp;#x1f170;"/> from "a"<linebreak/>
  <emoji name="ab" unicode="&amp;#x1f18e;"/> <emoji name="ab" unicode="&amp;#x1f18e;"/> from "ab"<linebreak/>
+ <emoji name="abacus" unicode="&amp;#x1f9ee;"/> <emoji name="abacus" unicode="&amp;#x1f9ee;"/> from "abacus"<linebreak/>
  <emoji name="abc" unicode="&amp;#x1f524;"/> <emoji name="abc" unicode="&amp;#x1f524;"/> from "abc"<linebreak/>
  <emoji name="abcd" unicode="&amp;#x1f521;"/> <emoji name="abcd" unicode="&amp;#x1f521;"/> from "abcd"<linebreak/>
  <emoji name="accept" unicode="&amp;#x1f251;"/> <emoji name="accept" unicode="&amp;#x1f251;"/> from "accept"<linebreak/>
+ <emoji name="accordion" unicode="&amp;#x1fa97;"/> <emoji name="accordion" unicode="&amp;#x1fa97;"/> from "accordion"<linebreak/>
+ <emoji name="adhesive_bandage" unicode="&amp;#x1fa79;"/> <emoji name="adhesive_bandage" unicode="&amp;#x1fa79;"/> from "adhesive_bandage"<linebreak/>
+ <emoji name="adult" unicode="&amp;#x1f9d1;"/> <emoji name="adult" unicode="&amp;#x1f9d1;"/> from "adult"<linebreak/>
  <emoji name="aerial_tramway" unicode="&amp;#x1f6a1;"/> <emoji name="aerial_tramway" unicode="&amp;#x1f6a1;"/> from "aerial_tramway"<linebreak/>
  <emoji name="afghanistan" unicode="&amp;#x1f1e6;&amp;#x1f1eb;"/> <emoji name="afghanistan" unicode="&amp;#x1f1e6;&amp;#x1f1eb;"/> from "afghanistan"<linebreak/>
  <emoji name="airplane" unicode="&amp;#x2708;"/> <emoji name="airplane" unicode="&amp;#x2708;"/> from "airplane"<linebreak/>
@@ -31,6 +35,7 @@
  <emoji name="ambulance" unicode="&amp;#x1f691;"/> <emoji name="ambulance" unicode="&amp;#x1f691;"/> from "ambulance"<linebreak/>
  <emoji name="american_samoa" unicode="&amp;#x1f1e6;&amp;#x1f1f8;"/> <emoji name="american_samoa" unicode="&amp;#x1f1e6;&amp;#x1f1f8;"/> from "american_samoa"<linebreak/>
  <emoji name="amphora" unicode="&amp;#x1f3fa;"/> <emoji name="amphora" unicode="&amp;#x1f3fa;"/> from "amphora"<linebreak/>
+ <emoji name="anatomical_heart" unicode="&amp;#x1fac0;"/> <emoji name="anatomical_heart" unicode="&amp;#x1fac0;"/> from "anatomical_heart"<linebreak/>
  <emoji name="anchor" unicode="&amp;#x2693;"/> <emoji name="anchor" unicode="&amp;#x2693;"/> from "anchor"<linebreak/>
  <emoji name="andorra" unicode="&amp;#x1f1e6;&amp;#x1f1e9;"/> <emoji name="andorra" unicode="&amp;#x1f1e6;&amp;#x1f1e9;"/> from "andorra"<linebreak/>
  <emoji name="angel" unicode="&amp;#x1f47c;"/> <emoji name="angel" unicode="&amp;#x1f47c;"/> from "angel"<linebreak/>
  <emoji name="art" unicode="&amp;#x1f3a8;"/> <emoji name="art" unicode="&amp;#x1f3a8;"/> from "art"<linebreak/>
  <emoji name="articulated_lorry" unicode="&amp;#x1f69b;"/> <emoji name="articulated_lorry" unicode="&amp;#x1f69b;"/> from "articulated_lorry"<linebreak/>
  <emoji name="artificial_satellite" unicode="&amp;#x1f6f0;"/> <emoji name="artificial_satellite" unicode="&amp;#x1f6f0;"/> from "artificial_satellite"<linebreak/>
+ <emoji name="artist" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f3a8;"/> <emoji name="artist" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f3a8;"/> from "artist"<linebreak/>
  <emoji name="aruba" unicode="&amp;#x1f1e6;&amp;#x1f1fc;"/> <emoji name="aruba" unicode="&amp;#x1f1e6;&amp;#x1f1fc;"/> from "aruba"<linebreak/>
- <emoji name="asterisk" unicode="&amp;#x002a;&amp;#x20e3;"/> <emoji name="asterisk" unicode="&amp;#x002a;&amp;#x20e3;"/> from "asterisk"<linebreak/>
+ <emoji name="ascension_island" unicode="&amp;#x1f1e6;&amp;#x1f1e8;"/> <emoji name="ascension_island" unicode="&amp;#x1f1e6;&amp;#x1f1e8;"/> from "ascension_island"<linebreak/>
+ <emoji name="asterisk" unicode="&amp;#x002a;&amp;#xfe0f;&amp;#x20e3;"/> <emoji name="asterisk" unicode="&amp;#x002a;&amp;#xfe0f;&amp;#x20e3;"/> from "asterisk"<linebreak/>
  <emoji name="astonished" unicode="&amp;#x1f632;"/> <emoji name="astonished" unicode="&amp;#x1f632;"/> from "astonished"<linebreak/>
+ <emoji name="astronaut" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f680;"/> <emoji name="astronaut" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f680;"/> from "astronaut"<linebreak/>
  <emoji name="athletic_shoe" unicode="&amp;#x1f45f;"/> <emoji name="athletic_shoe" unicode="&amp;#x1f45f;"/> from "athletic_shoe"<linebreak/>
  <emoji name="atm" unicode="&amp;#x1f3e7;"/> <emoji name="atm" unicode="&amp;#x1f3e7;"/> from "atm"<linebreak/>
  <emoji name="atom_symbol" unicode="&amp;#x269b;"/> <emoji name="atom_symbol" unicode="&amp;#x269b;"/> from "atom_symbol"<linebreak/>
  <emoji name="australia" unicode="&amp;#x1f1e6;&amp;#x1f1fa;"/> <emoji name="australia" unicode="&amp;#x1f1e6;&amp;#x1f1fa;"/> from "australia"<linebreak/>
  <emoji name="austria" unicode="&amp;#x1f1e6;&amp;#x1f1f9;"/> <emoji name="austria" unicode="&amp;#x1f1e6;&amp;#x1f1f9;"/> from "austria"<linebreak/>
+ <emoji name="auto_rickshaw" unicode="&amp;#x1f6fa;"/> <emoji name="auto_rickshaw" unicode="&amp;#x1f6fa;"/> from "auto_rickshaw"<linebreak/>
  <emoji name="avocado" unicode="&amp;#x1f951;"/> <emoji name="avocado" unicode="&amp;#x1f951;"/> from "avocado"<linebreak/>
+ <emoji name="axe" unicode="&amp;#x1fa93;"/> <emoji name="axe" unicode="&amp;#x1fa93;"/> from "axe"<linebreak/>
  <emoji name="azerbaijan" unicode="&amp;#x1f1e6;&amp;#x1f1ff;"/> <emoji name="azerbaijan" unicode="&amp;#x1f1e6;&amp;#x1f1ff;"/> from "azerbaijan"<linebreak/>
  <emoji name="b" unicode="&amp;#x1f171;"/> <emoji name="b" unicode="&amp;#x1f171;"/> from "b"<linebreak/>
  <emoji name="baby" unicode="&amp;#x1f476;"/> <emoji name="baby" unicode="&amp;#x1f476;"/> from "baby"<linebreak/>
  <emoji name="baby_symbol" unicode="&amp;#x1f6bc;"/> <emoji name="baby_symbol" unicode="&amp;#x1f6bc;"/> from "baby_symbol"<linebreak/>
  <emoji name="back" unicode="&amp;#x1f519;"/> <emoji name="back" unicode="&amp;#x1f519;"/> from "back"<linebreak/>
  <emoji name="bacon" unicode="&amp;#x1f953;"/> <emoji name="bacon" unicode="&amp;#x1f953;"/> from "bacon"<linebreak/>
+ <emoji name="badger" unicode="&amp;#x1f9a1;"/> <emoji name="badger" unicode="&amp;#x1f9a1;"/> from "badger"<linebreak/>
  <emoji name="badminton" unicode="&amp;#x1f3f8;"/> <emoji name="badminton" unicode="&amp;#x1f3f8;"/> from "badminton"<linebreak/>
+ <emoji name="bagel" unicode="&amp;#x1f96f;"/> <emoji name="bagel" unicode="&amp;#x1f96f;"/> from "bagel"<linebreak/>
  <emoji name="baggage_claim" unicode="&amp;#x1f6c4;"/> <emoji name="baggage_claim" unicode="&amp;#x1f6c4;"/> from "baggage_claim"<linebreak/>
  <emoji name="baguette_bread" unicode="&amp;#x1f956;"/> <emoji name="baguette_bread" unicode="&amp;#x1f956;"/> from "baguette_bread"<linebreak/>
  <emoji name="bahamas" unicode="&amp;#x1f1e7;&amp;#x1f1f8;"/> <emoji name="bahamas" unicode="&amp;#x1f1e7;&amp;#x1f1f8;"/> from "bahamas"<linebreak/>
  <emoji name="bahrain" unicode="&amp;#x1f1e7;&amp;#x1f1ed;"/> <emoji name="bahrain" unicode="&amp;#x1f1e7;&amp;#x1f1ed;"/> from "bahrain"<linebreak/>
  <emoji name="balance_scale" unicode="&amp;#x2696;"/> <emoji name="balance_scale" unicode="&amp;#x2696;"/> from "balance_scale"<linebreak/>
+ <emoji name="bald_man" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9b2;"/> <emoji name="bald_man" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9b2;"/> from "bald_man"<linebreak/>
+ <emoji name="bald_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9b2;"/> <emoji name="bald_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9b2;"/> from "bald_woman"<linebreak/>
+ <emoji name="ballet_shoes" unicode="&amp;#x1fa70;"/> <emoji name="ballet_shoes" unicode="&amp;#x1fa70;"/> from "ballet_shoes"<linebreak/>
  <emoji name="balloon" unicode="&amp;#x1f388;"/> <emoji name="balloon" unicode="&amp;#x1f388;"/> from "balloon"<linebreak/>
  <emoji name="ballot_box" unicode="&amp;#x1f5f3;"/> <emoji name="ballot_box" unicode="&amp;#x1f5f3;"/> from "ballot_box"<linebreak/>
  <emoji name="ballot_box_with_check" unicode="&amp;#x2611;"/> <emoji name="ballot_box_with_check" unicode="&amp;#x2611;"/> from "ballot_box_with_check"<linebreak/>
  <emoji name="banana" unicode="&amp;#x1f34c;"/> <emoji name="banana" unicode="&amp;#x1f34c;"/> from "banana"<linebreak/>
  <emoji name="bangbang" unicode="&amp;#x203c;"/> <emoji name="bangbang" unicode="&amp;#x203c;"/> from "bangbang"<linebreak/>
  <emoji name="bangladesh" unicode="&amp;#x1f1e7;&amp;#x1f1e9;"/> <emoji name="bangladesh" unicode="&amp;#x1f1e7;&amp;#x1f1e9;"/> from "bangladesh"<linebreak/>
+ <emoji name="banjo" unicode="&amp;#x1fa95;"/> <emoji name="banjo" unicode="&amp;#x1fa95;"/> from "banjo"<linebreak/>
  <emoji name="bank" unicode="&amp;#x1f3e6;"/> <emoji name="bank" unicode="&amp;#x1f3e6;"/> from "bank"<linebreak/>
  <emoji name="bar_chart" unicode="&amp;#x1f4ca;"/> <emoji name="bar_chart" unicode="&amp;#x1f4ca;"/> from "bar_chart"<linebreak/>
  <emoji name="barbados" unicode="&amp;#x1f1e7;&amp;#x1f1e7;"/> <emoji name="barbados" unicode="&amp;#x1f1e7;&amp;#x1f1e7;"/> from "barbados"<linebreak/>
  <emoji name="barber" unicode="&amp;#x1f488;"/> <emoji name="barber" unicode="&amp;#x1f488;"/> from "barber"<linebreak/>
  <emoji name="baseball" unicode="&amp;#x26be;"/> <emoji name="baseball" unicode="&amp;#x26be;"/> from "baseball"<linebreak/>
+ <emoji name="basket" unicode="&amp;#x1f9fa;"/> <emoji name="basket" unicode="&amp;#x1f9fa;"/> from "basket"<linebreak/>
  <emoji name="basketball" unicode="&amp;#x1f3c0;"/> <emoji name="basketball" unicode="&amp;#x1f3c0;"/> from "basketball"<linebreak/>
- <emoji name="basketball_man" unicode="&amp;#x26f9;"/> <emoji name="basketball_man" unicode="&amp;#x26f9;"/> from "basketball_man"<linebreak/>
- <emoji name="basketball_woman" unicode="&amp;#x26f9;&amp;#x2640;"/> <emoji name="basketball_woman" unicode="&amp;#x26f9;&amp;#x2640;"/> from "basketball_woman"<linebreak/>
+ <emoji name="basketball_man" unicode="&amp;#x26f9;&amp;#xfe0f;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="basketball_man" unicode="&amp;#x26f9;&amp;#xfe0f;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "basketball_man"<linebreak/>
+ <emoji name="basketball_woman" unicode="&amp;#x26f9;&amp;#xfe0f;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="basketball_woman" unicode="&amp;#x26f9;&amp;#xfe0f;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "basketball_woman"<linebreak/>
  <emoji name="bat" unicode="&amp;#x1f987;"/> <emoji name="bat" unicode="&amp;#x1f987;"/> from "bat"<linebreak/>
  <emoji name="bath" unicode="&amp;#x1f6c0;"/> <emoji name="bath" unicode="&amp;#x1f6c0;"/> from "bath"<linebreak/>
  <emoji name="bathtub" unicode="&amp;#x1f6c1;"/> <emoji name="bathtub" unicode="&amp;#x1f6c1;"/> from "bathtub"<linebreak/>
  <emoji name="battery" unicode="&amp;#x1f50b;"/> <emoji name="battery" unicode="&amp;#x1f50b;"/> from "battery"<linebreak/>
  <emoji name="beach_umbrella" unicode="&amp;#x1f3d6;"/> <emoji name="beach_umbrella" unicode="&amp;#x1f3d6;"/> from "beach_umbrella"<linebreak/>
  <emoji name="bear" unicode="&amp;#x1f43b;"/> <emoji name="bear" unicode="&amp;#x1f43b;"/> from "bear"<linebreak/>
+ <emoji name="bearded_person" unicode="&amp;#x1f9d4;"/> <emoji name="bearded_person" unicode="&amp;#x1f9d4;"/> from "bearded_person"<linebreak/>
+ <emoji name="beaver" unicode="&amp;#x1f9ab;"/> <emoji name="beaver" unicode="&amp;#x1f9ab;"/> from "beaver"<linebreak/>
  <emoji name="bed" unicode="&amp;#x1f6cf;"/> <emoji name="bed" unicode="&amp;#x1f6cf;"/> from "bed"<linebreak/>
  <emoji name="bee" unicode="&amp;#x1f41d;"/> <emoji name="bee" unicode="&amp;#x1f41d;"/> from "bee"<linebreak/>
  <emoji name="beer" unicode="&amp;#x1f37a;"/> <emoji name="beer" unicode="&amp;#x1f37a;"/> from "beer"<linebreak/>
  <emoji name="beers" unicode="&amp;#x1f37b;"/> <emoji name="beers" unicode="&amp;#x1f37b;"/> from "beers"<linebreak/>
- <emoji name="beetle" unicode="&amp;#x1f41e;"/> <emoji name="beetle" unicode="&amp;#x1f41e;"/> from "beetle"<linebreak/>
+ <emoji name="beetle" unicode="&amp;#x1fab2;"/> <emoji name="beetle" unicode="&amp;#x1fab2;"/> from "beetle"<linebreak/>
  <emoji name="beginner" unicode="&amp;#x1f530;"/> <emoji name="beginner" unicode="&amp;#x1f530;"/> from "beginner"<linebreak/>
  <emoji name="belarus" unicode="&amp;#x1f1e7;&amp;#x1f1fe;"/> <emoji name="belarus" unicode="&amp;#x1f1e7;&amp;#x1f1fe;"/> from "belarus"<linebreak/>
  <emoji name="belgium" unicode="&amp;#x1f1e7;&amp;#x1f1ea;"/> <emoji name="belgium" unicode="&amp;#x1f1e7;&amp;#x1f1ea;"/> from "belgium"<linebreak/>
  <emoji name="belize" unicode="&amp;#x1f1e7;&amp;#x1f1ff;"/> <emoji name="belize" unicode="&amp;#x1f1e7;&amp;#x1f1ff;"/> from "belize"<linebreak/>
  <emoji name="bell" unicode="&amp;#x1f514;"/> <emoji name="bell" unicode="&amp;#x1f514;"/> from "bell"<linebreak/>
+ <emoji name="bell_pepper" unicode="&amp;#x1fad1;"/> <emoji name="bell_pepper" unicode="&amp;#x1fad1;"/> from "bell_pepper"<linebreak/>
  <emoji name="bellhop_bell" unicode="&amp;#x1f6ce;"/> <emoji name="bellhop_bell" unicode="&amp;#x1f6ce;"/> from "bellhop_bell"<linebreak/>
  <emoji name="benin" unicode="&amp;#x1f1e7;&amp;#x1f1ef;"/> <emoji name="benin" unicode="&amp;#x1f1e7;&amp;#x1f1ef;"/> from "benin"<linebreak/>
  <emoji name="bento" unicode="&amp;#x1f371;"/> <emoji name="bento" unicode="&amp;#x1f371;"/> from "bento"<linebreak/>
  <emoji name="bermuda" unicode="&amp;#x1f1e7;&amp;#x1f1f2;"/> <emoji name="bermuda" unicode="&amp;#x1f1e7;&amp;#x1f1f2;"/> from "bermuda"<linebreak/>
+ <emoji name="beverage_box" unicode="&amp;#x1f9c3;"/> <emoji name="beverage_box" unicode="&amp;#x1f9c3;"/> from "beverage_box"<linebreak/>
  <emoji name="bhutan" unicode="&amp;#x1f1e7;&amp;#x1f1f9;"/> <emoji name="bhutan" unicode="&amp;#x1f1e7;&amp;#x1f1f9;"/> from "bhutan"<linebreak/>
  <emoji name="bicyclist" unicode="&amp;#x1f6b4;"/> <emoji name="bicyclist" unicode="&amp;#x1f6b4;"/> from "bicyclist"<linebreak/>
  <emoji name="bike" unicode="&amp;#x1f6b2;"/> <emoji name="bike" unicode="&amp;#x1f6b2;"/> from "bike"<linebreak/>
- <emoji name="biking_man" unicode="&amp;#x1f6b4;"/> <emoji name="biking_man" unicode="&amp;#x1f6b4;"/> from "biking_man"<linebreak/>
- <emoji name="biking_woman" unicode="&amp;#x1f6b4;&amp;#x2640;"/> <emoji name="biking_woman" unicode="&amp;#x1f6b4;&amp;#x2640;"/> from "biking_woman"<linebreak/>
+ <emoji name="biking_man" unicode="&amp;#x1f6b4;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="biking_man" unicode="&amp;#x1f6b4;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "biking_man"<linebreak/>
+ <emoji name="biking_woman" unicode="&amp;#x1f6b4;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="biking_woman" unicode="&amp;#x1f6b4;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "biking_woman"<linebreak/>
  <emoji name="bikini" unicode="&amp;#x1f459;"/> <emoji name="bikini" unicode="&amp;#x1f459;"/> from "bikini"<linebreak/>
+ <emoji name="billed_cap" unicode="&amp;#x1f9e2;"/> <emoji name="billed_cap" unicode="&amp;#x1f9e2;"/> from "billed_cap"<linebreak/>
  <emoji name="biohazard" unicode="&amp;#x2623;"/> <emoji name="biohazard" unicode="&amp;#x2623;"/> from "biohazard"<linebreak/>
  <emoji name="bird" unicode="&amp;#x1f426;"/> <emoji name="bird" unicode="&amp;#x1f426;"/> from "bird"<linebreak/>
  <emoji name="birthday" unicode="&amp;#x1f382;"/> <emoji name="birthday" unicode="&amp;#x1f382;"/> from "birthday"<linebreak/>
+ <emoji name="bison" unicode="&amp;#x1f9ac;"/> <emoji name="bison" unicode="&amp;#x1f9ac;"/> from "bison"<linebreak/>
+ <emoji name="black_cat" unicode="&amp;#x1f408;&amp;#x200d;&amp;#x2b1b;"/> <emoji name="black_cat" unicode="&amp;#x1f408;&amp;#x200d;&amp;#x2b1b;"/> from "black_cat"<linebreak/>
  <emoji name="black_circle" unicode="&amp;#x26ab;"/> <emoji name="black_circle" unicode="&amp;#x26ab;"/> from "black_circle"<linebreak/>
  <emoji name="black_flag" unicode="&amp;#x1f3f4;"/> <emoji name="black_flag" unicode="&amp;#x1f3f4;"/> from "black_flag"<linebreak/>
  <emoji name="black_heart" unicode="&amp;#x1f5a4;"/> <emoji name="black_heart" unicode="&amp;#x1f5a4;"/> from "black_heart"<linebreak/>
  <emoji name="black_nib" unicode="&amp;#x2712;"/> <emoji name="black_nib" unicode="&amp;#x2712;"/> from "black_nib"<linebreak/>
  <emoji name="black_small_square" unicode="&amp;#x25aa;"/> <emoji name="black_small_square" unicode="&amp;#x25aa;"/> from "black_small_square"<linebreak/>
  <emoji name="black_square_button" unicode="&amp;#x1f532;"/> <emoji name="black_square_button" unicode="&amp;#x1f532;"/> from "black_square_button"<linebreak/>
- <emoji name="blonde_man" unicode="&amp;#x1f471;"/> <emoji name="blonde_man" unicode="&amp;#x1f471;"/> from "blonde_man"<linebreak/>
- <emoji name="blonde_woman" unicode="&amp;#x1f471;&amp;#x2640;"/> <emoji name="blonde_woman" unicode="&amp;#x1f471;&amp;#x2640;"/> from "blonde_woman"<linebreak/>
+ <emoji name="blond_haired_man" unicode="&amp;#x1f471;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="blond_haired_man" unicode="&amp;#x1f471;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "blond_haired_man"<linebreak/>
+ <emoji name="blond_haired_person" unicode="&amp;#x1f471;"/> <emoji name="blond_haired_person" unicode="&amp;#x1f471;"/> from "blond_haired_person"<linebreak/>
+ <emoji name="blond_haired_woman" unicode="&amp;#x1f471;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="blond_haired_woman" unicode="&amp;#x1f471;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "blond_haired_woman"<linebreak/>
+ <emoji name="blonde_woman" unicode="&amp;#x1f471;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="blonde_woman" unicode="&amp;#x1f471;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "blonde_woman"<linebreak/>
  <emoji name="blossom" unicode="&amp;#x1f33c;"/> <emoji name="blossom" unicode="&amp;#x1f33c;"/> from "blossom"<linebreak/>
  <emoji name="blowfish" unicode="&amp;#x1f421;"/> <emoji name="blowfish" unicode="&amp;#x1f421;"/> from "blowfish"<linebreak/>
  <emoji name="blue_book" unicode="&amp;#x1f4d8;"/> <emoji name="blue_book" unicode="&amp;#x1f4d8;"/> from "blue_book"<linebreak/>
  <emoji name="blue_car" unicode="&amp;#x1f699;"/> <emoji name="blue_car" unicode="&amp;#x1f699;"/> from "blue_car"<linebreak/>
  <emoji name="blue_heart" unicode="&amp;#x1f499;"/> <emoji name="blue_heart" unicode="&amp;#x1f499;"/> from "blue_heart"<linebreak/>
+ <emoji name="blue_square" unicode="&amp;#x1f7e6;"/> <emoji name="blue_square" unicode="&amp;#x1f7e6;"/> from "blue_square"<linebreak/>
+ <emoji name="blueberries" unicode="&amp;#x1fad0;"/> <emoji name="blueberries" unicode="&amp;#x1fad0;"/> from "blueberries"<linebreak/>
  <emoji name="blush" unicode="&amp;#x1f60a;"/> <emoji name="blush" unicode="&amp;#x1f60a;"/> from "blush"<linebreak/>
  <emoji name="boar" unicode="&amp;#x1f417;"/> <emoji name="boar" unicode="&amp;#x1f417;"/> from "boar"<linebreak/>
  <emoji name="boat" unicode="&amp;#x26f5;"/> <emoji name="boat" unicode="&amp;#x26f5;"/> from "boat"<linebreak/>
  <emoji name="bolivia" unicode="&amp;#x1f1e7;&amp;#x1f1f4;"/> <emoji name="bolivia" unicode="&amp;#x1f1e7;&amp;#x1f1f4;"/> from "bolivia"<linebreak/>
  <emoji name="bomb" unicode="&amp;#x1f4a3;"/> <emoji name="bomb" unicode="&amp;#x1f4a3;"/> from "bomb"<linebreak/>
+ <emoji name="bone" unicode="&amp;#x1f9b4;"/> <emoji name="bone" unicode="&amp;#x1f9b4;"/> from "bone"<linebreak/>
  <emoji name="book" unicode="&amp;#x1f4d6;"/> <emoji name="book" unicode="&amp;#x1f4d6;"/> from "book"<linebreak/>
  <emoji name="bookmark" unicode="&amp;#x1f516;"/> <emoji name="bookmark" unicode="&amp;#x1f516;"/> from "bookmark"<linebreak/>
  <emoji name="bookmark_tabs" unicode="&amp;#x1f4d1;"/> <emoji name="bookmark_tabs" unicode="&amp;#x1f4d1;"/> from "bookmark_tabs"<linebreak/>
  <emoji name="books" unicode="&amp;#x1f4da;"/> <emoji name="books" unicode="&amp;#x1f4da;"/> from "books"<linebreak/>
  <emoji name="boom" unicode="&amp;#x1f4a5;"/> <emoji name="boom" unicode="&amp;#x1f4a5;"/> from "boom"<linebreak/>
+ <emoji name="boomerang" unicode="&amp;#x1fa83;"/> <emoji name="boomerang" unicode="&amp;#x1fa83;"/> from "boomerang"<linebreak/>
  <emoji name="boot" unicode="&amp;#x1f462;"/> <emoji name="boot" unicode="&amp;#x1f462;"/> from "boot"<linebreak/>
  <emoji name="bosnia_herzegovina" unicode="&amp;#x1f1e7;&amp;#x1f1e6;"/> <emoji name="bosnia_herzegovina" unicode="&amp;#x1f1e7;&amp;#x1f1e6;"/> from "bosnia_herzegovina"<linebreak/>
  <emoji name="botswana" unicode="&amp;#x1f1e7;&amp;#x1f1fc;"/> <emoji name="botswana" unicode="&amp;#x1f1e7;&amp;#x1f1fc;"/> from "botswana"<linebreak/>
+ <emoji name="bouncing_ball_man" unicode="&amp;#x26f9;&amp;#xfe0f;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="bouncing_ball_man" unicode="&amp;#x26f9;&amp;#xfe0f;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "bouncing_ball_man"<linebreak/>
+ <emoji name="bouncing_ball_person" unicode="&amp;#x26f9;"/> <emoji name="bouncing_ball_person" unicode="&amp;#x26f9;"/> from "bouncing_ball_person"<linebreak/>
+ <emoji name="bouncing_ball_woman" unicode="&amp;#x26f9;&amp;#xfe0f;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="bouncing_ball_woman" unicode="&amp;#x26f9;&amp;#xfe0f;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "bouncing_ball_woman"<linebreak/>
  <emoji name="bouquet" unicode="&amp;#x1f490;"/> <emoji name="bouquet" unicode="&amp;#x1f490;"/> from "bouquet"<linebreak/>
+ <emoji name="bouvet_island" unicode="&amp;#x1f1e7;&amp;#x1f1fb;"/> <emoji name="bouvet_island" unicode="&amp;#x1f1e7;&amp;#x1f1fb;"/> from "bouvet_island"<linebreak/>
  <emoji name="bow" unicode="&amp;#x1f647;"/> <emoji name="bow" unicode="&amp;#x1f647;"/> from "bow"<linebreak/>
  <emoji name="bow_and_arrow" unicode="&amp;#x1f3f9;"/> <emoji name="bow_and_arrow" unicode="&amp;#x1f3f9;"/> from "bow_and_arrow"<linebreak/>
- <emoji name="bowing_man" unicode="&amp;#x1f647;"/> <emoji name="bowing_man" unicode="&amp;#x1f647;"/> from "bowing_man"<linebreak/>
- <emoji name="bowing_woman" unicode="&amp;#x1f647;&amp;#x2640;"/> <emoji name="bowing_woman" unicode="&amp;#x1f647;&amp;#x2640;"/> from "bowing_woman"<linebreak/>
+ <emoji name="bowing_man" unicode="&amp;#x1f647;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="bowing_man" unicode="&amp;#x1f647;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "bowing_man"<linebreak/>
+ <emoji name="bowing_woman" unicode="&amp;#x1f647;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="bowing_woman" unicode="&amp;#x1f647;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "bowing_woman"<linebreak/>
+ <emoji name="bowl_with_spoon" unicode="&amp;#x1f963;"/> <emoji name="bowl_with_spoon" unicode="&amp;#x1f963;"/> from "bowl_with_spoon"<linebreak/>
  <emoji name="bowling" unicode="&amp;#x1f3b3;"/> <emoji name="bowling" unicode="&amp;#x1f3b3;"/> from "bowling"<linebreak/>
  <emoji name="boxing_glove" unicode="&amp;#x1f94a;"/> <emoji name="boxing_glove" unicode="&amp;#x1f94a;"/> from "boxing_glove"<linebreak/>
  <emoji name="boy" unicode="&amp;#x1f466;"/> <emoji name="boy" unicode="&amp;#x1f466;"/> from "boy"<linebreak/>
+ <emoji name="brain" unicode="&amp;#x1f9e0;"/> <emoji name="brain" unicode="&amp;#x1f9e0;"/> from "brain"<linebreak/>
  <emoji name="brazil" unicode="&amp;#x1f1e7;&amp;#x1f1f7;"/> <emoji name="brazil" unicode="&amp;#x1f1e7;&amp;#x1f1f7;"/> from "brazil"<linebreak/>
  <emoji name="bread" unicode="&amp;#x1f35e;"/> <emoji name="bread" unicode="&amp;#x1f35e;"/> from "bread"<linebreak/>
- <emoji name="bride_with_veil" unicode="&amp;#x1f470;"/> <emoji name="bride_with_veil" unicode="&amp;#x1f470;"/> from "bride_with_veil"<linebreak/>
+ <emoji name="breast_feeding" unicode="&amp;#x1f931;"/> <emoji name="breast_feeding" unicode="&amp;#x1f931;"/> from "breast_feeding"<linebreak/>
+ <emoji name="bricks" unicode="&amp;#x1f9f1;"/> <emoji name="bricks" unicode="&amp;#x1f9f1;"/> from "bricks"<linebreak/>
+ <emoji name="bride_with_veil" unicode="&amp;#x1f470;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="bride_with_veil" unicode="&amp;#x1f470;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "bride_with_veil"<linebreak/>
  <emoji name="bridge_at_night" unicode="&amp;#x1f309;"/> <emoji name="bridge_at_night" unicode="&amp;#x1f309;"/> from "bridge_at_night"<linebreak/>
  <emoji name="briefcase" unicode="&amp;#x1f4bc;"/> <emoji name="briefcase" unicode="&amp;#x1f4bc;"/> from "briefcase"<linebreak/>
  <emoji name="british_indian_ocean_territory" unicode="&amp;#x1f1ee;&amp;#x1f1f4;"/> <emoji name="british_indian_ocean_territory" unicode="&amp;#x1f1ee;&amp;#x1f1f4;"/> from "british_indian_ocean_territory"<linebreak/>
  <emoji name="british_virgin_islands" unicode="&amp;#x1f1fb;&amp;#x1f1ec;"/> <emoji name="british_virgin_islands" unicode="&amp;#x1f1fb;&amp;#x1f1ec;"/> from "british_virgin_islands"<linebreak/>
+ <emoji name="broccoli" unicode="&amp;#x1f966;"/> <emoji name="broccoli" unicode="&amp;#x1f966;"/> from "broccoli"<linebreak/>
  <emoji name="broken_heart" unicode="&amp;#x1f494;"/> <emoji name="broken_heart" unicode="&amp;#x1f494;"/> from "broken_heart"<linebreak/>
+ <emoji name="broom" unicode="&amp;#x1f9f9;"/> <emoji name="broom" unicode="&amp;#x1f9f9;"/> from "broom"<linebreak/>
+ <emoji name="brown_circle" unicode="&amp;#x1f7e4;"/> <emoji name="brown_circle" unicode="&amp;#x1f7e4;"/> from "brown_circle"<linebreak/>
+ <emoji name="brown_heart" unicode="&amp;#x1f90e;"/> <emoji name="brown_heart" unicode="&amp;#x1f90e;"/> from "brown_heart"<linebreak/>
+ <emoji name="brown_square" unicode="&amp;#x1f7eb;"/> <emoji name="brown_square" unicode="&amp;#x1f7eb;"/> from "brown_square"<linebreak/>
  <emoji name="brunei" unicode="&amp;#x1f1e7;&amp;#x1f1f3;"/> <emoji name="brunei" unicode="&amp;#x1f1e7;&amp;#x1f1f3;"/> from "brunei"<linebreak/>
+ <emoji name="bubble_tea" unicode="&amp;#x1f9cb;"/> <emoji name="bubble_tea" unicode="&amp;#x1f9cb;"/> from "bubble_tea"<linebreak/>
+ <emoji name="bucket" unicode="&amp;#x1faa3;"/> <emoji name="bucket" unicode="&amp;#x1faa3;"/> from "bucket"<linebreak/>
  <emoji name="bug" unicode="&amp;#x1f41b;"/> <emoji name="bug" unicode="&amp;#x1f41b;"/> from "bug"<linebreak/>
  <emoji name="building_construction" unicode="&amp;#x1f3d7;"/> <emoji name="building_construction" unicode="&amp;#x1f3d7;"/> from "building_construction"<linebreak/>
  <emoji name="bulb" unicode="&amp;#x1f4a1;"/> <emoji name="bulb" unicode="&amp;#x1f4a1;"/> from "bulb"<linebreak/>
  <emoji name="busstop" unicode="&amp;#x1f68f;"/> <emoji name="busstop" unicode="&amp;#x1f68f;"/> from "busstop"<linebreak/>
  <emoji name="bust_in_silhouette" unicode="&amp;#x1f464;"/> <emoji name="bust_in_silhouette" unicode="&amp;#x1f464;"/> from "bust_in_silhouette"<linebreak/>
  <emoji name="busts_in_silhouette" unicode="&amp;#x1f465;"/> <emoji name="busts_in_silhouette" unicode="&amp;#x1f465;"/> from "busts_in_silhouette"<linebreak/>
+ <emoji name="butter" unicode="&amp;#x1f9c8;"/> <emoji name="butter" unicode="&amp;#x1f9c8;"/> from "butter"<linebreak/>
  <emoji name="butterfly" unicode="&amp;#x1f98b;"/> <emoji name="butterfly" unicode="&amp;#x1f98b;"/> from "butterfly"<linebreak/>
  <emoji name="cactus" unicode="&amp;#x1f335;"/> <emoji name="cactus" unicode="&amp;#x1f335;"/> from "cactus"<linebreak/>
  <emoji name="cake" unicode="&amp;#x1f370;"/> <emoji name="cake" unicode="&amp;#x1f370;"/> from "cake"<linebreak/>
  <emoji name="cancer" unicode="&amp;#x264b;"/> <emoji name="cancer" unicode="&amp;#x264b;"/> from "cancer"<linebreak/>
  <emoji name="candle" unicode="&amp;#x1f56f;"/> <emoji name="candle" unicode="&amp;#x1f56f;"/> from "candle"<linebreak/>
  <emoji name="candy" unicode="&amp;#x1f36c;"/> <emoji name="candy" unicode="&amp;#x1f36c;"/> from "candy"<linebreak/>
+ <emoji name="canned_food" unicode="&amp;#x1f96b;"/> <emoji name="canned_food" unicode="&amp;#x1f96b;"/> from "canned_food"<linebreak/>
  <emoji name="canoe" unicode="&amp;#x1f6f6;"/> <emoji name="canoe" unicode="&amp;#x1f6f6;"/> from "canoe"<linebreak/>
  <emoji name="cape_verde" unicode="&amp;#x1f1e8;&amp;#x1f1fb;"/> <emoji name="cape_verde" unicode="&amp;#x1f1e8;&amp;#x1f1fb;"/> from "cape_verde"<linebreak/>
  <emoji name="capital_abcd" unicode="&amp;#x1f520;"/> <emoji name="capital_abcd" unicode="&amp;#x1f520;"/> from "capital_abcd"<linebreak/>
  <emoji name="card_index_dividers" unicode="&amp;#x1f5c2;"/> <emoji name="card_index_dividers" unicode="&amp;#x1f5c2;"/> from "card_index_dividers"<linebreak/>
  <emoji name="caribbean_netherlands" unicode="&amp;#x1f1e7;&amp;#x1f1f6;"/> <emoji name="caribbean_netherlands" unicode="&amp;#x1f1e7;&amp;#x1f1f6;"/> from "caribbean_netherlands"<linebreak/>
  <emoji name="carousel_horse" unicode="&amp;#x1f3a0;"/> <emoji name="carousel_horse" unicode="&amp;#x1f3a0;"/> from "carousel_horse"<linebreak/>
+ <emoji name="carpentry_saw" unicode="&amp;#x1fa9a;"/> <emoji name="carpentry_saw" unicode="&amp;#x1fa9a;"/> from "carpentry_saw"<linebreak/>
  <emoji name="carrot" unicode="&amp;#x1f955;"/> <emoji name="carrot" unicode="&amp;#x1f955;"/> from "carrot"<linebreak/>
+ <emoji name="cartwheeling" unicode="&amp;#x1f938;"/> <emoji name="cartwheeling" unicode="&amp;#x1f938;"/> from "cartwheeling"<linebreak/>
  <emoji name="cat" unicode="&amp;#x1f431;"/> <emoji name="cat" unicode="&amp;#x1f431;"/> from "cat"<linebreak/>
  <emoji name="cat2" unicode="&amp;#x1f408;"/> <emoji name="cat2" unicode="&amp;#x1f408;"/> from "cat2"<linebreak/>
  <emoji name="cayman_islands" unicode="&amp;#x1f1f0;&amp;#x1f1fe;"/> <emoji name="cayman_islands" unicode="&amp;#x1f1f0;&amp;#x1f1fe;"/> from "cayman_islands"<linebreak/>
  <emoji name="cd" unicode="&amp;#x1f4bf;"/> <emoji name="cd" unicode="&amp;#x1f4bf;"/> from "cd"<linebreak/>
  <emoji name="central_african_republic" unicode="&amp;#x1f1e8;&amp;#x1f1eb;"/> <emoji name="central_african_republic" unicode="&amp;#x1f1e8;&amp;#x1f1eb;"/> from "central_african_republic"<linebreak/>
+ <emoji name="ceuta_melilla" unicode="&amp;#x1f1ea;&amp;#x1f1e6;"/> <emoji name="ceuta_melilla" unicode="&amp;#x1f1ea;&amp;#x1f1e6;"/> from "ceuta_melilla"<linebreak/>
  <emoji name="chad" unicode="&amp;#x1f1f9;&amp;#x1f1e9;"/> <emoji name="chad" unicode="&amp;#x1f1f9;&amp;#x1f1e9;"/> from "chad"<linebreak/>
  <emoji name="chains" unicode="&amp;#x26d3;"/> <emoji name="chains" unicode="&amp;#x26d3;"/> from "chains"<linebreak/>
+ <emoji name="chair" unicode="&amp;#x1fa91;"/> <emoji name="chair" unicode="&amp;#x1fa91;"/> from "chair"<linebreak/>
  <emoji name="champagne" unicode="&amp;#x1f37e;"/> <emoji name="champagne" unicode="&amp;#x1f37e;"/> from "champagne"<linebreak/>
  <emoji name="chart" unicode="&amp;#x1f4b9;"/> <emoji name="chart" unicode="&amp;#x1f4b9;"/> from "chart"<linebreak/>
  <emoji name="chart_with_downwards_trend" unicode="&amp;#x1f4c9;"/> <emoji name="chart_with_downwards_trend" unicode="&amp;#x1f4c9;"/> from "chart_with_downwards_trend"<linebreak/>
  <emoji name="cheese" unicode="&amp;#x1f9c0;"/> <emoji name="cheese" unicode="&amp;#x1f9c0;"/> from "cheese"<linebreak/>
  <emoji name="cherries" unicode="&amp;#x1f352;"/> <emoji name="cherries" unicode="&amp;#x1f352;"/> from "cherries"<linebreak/>
  <emoji name="cherry_blossom" unicode="&amp;#x1f338;"/> <emoji name="cherry_blossom" unicode="&amp;#x1f338;"/> from "cherry_blossom"<linebreak/>
+ <emoji name="chess_pawn" unicode="&amp;#x265f;"/> <emoji name="chess_pawn" unicode="&amp;#x265f;"/> from "chess_pawn"<linebreak/>
  <emoji name="chestnut" unicode="&amp;#x1f330;"/> <emoji name="chestnut" unicode="&amp;#x1f330;"/> from "chestnut"<linebreak/>
  <emoji name="chicken" unicode="&amp;#x1f414;"/> <emoji name="chicken" unicode="&amp;#x1f414;"/> from "chicken"<linebreak/>
+ <emoji name="child" unicode="&amp;#x1f9d2;"/> <emoji name="child" unicode="&amp;#x1f9d2;"/> from "child"<linebreak/>
  <emoji name="children_crossing" unicode="&amp;#x1f6b8;"/> <emoji name="children_crossing" unicode="&amp;#x1f6b8;"/> from "children_crossing"<linebreak/>
  <emoji name="chile" unicode="&amp;#x1f1e8;&amp;#x1f1f1;"/> <emoji name="chile" unicode="&amp;#x1f1e8;&amp;#x1f1f1;"/> from "chile"<linebreak/>
  <emoji name="chipmunk" unicode="&amp;#x1f43f;"/> <emoji name="chipmunk" unicode="&amp;#x1f43f;"/> from "chipmunk"<linebreak/>
  <emoji name="chocolate_bar" unicode="&amp;#x1f36b;"/> <emoji name="chocolate_bar" unicode="&amp;#x1f36b;"/> from "chocolate_bar"<linebreak/>
+ <emoji name="chopsticks" unicode="&amp;#x1f962;"/> <emoji name="chopsticks" unicode="&amp;#x1f962;"/> from "chopsticks"<linebreak/>
  <emoji name="christmas_island" unicode="&amp;#x1f1e8;&amp;#x1f1fd;"/> <emoji name="christmas_island" unicode="&amp;#x1f1e8;&amp;#x1f1fd;"/> from "christmas_island"<linebreak/>
  <emoji name="christmas_tree" unicode="&amp;#x1f384;"/> <emoji name="christmas_tree" unicode="&amp;#x1f384;"/> from "christmas_tree"<linebreak/>
  <emoji name="church" unicode="&amp;#x26ea;"/> <emoji name="church" unicode="&amp;#x26ea;"/> from "church"<linebreak/>
  <emoji name="clap" unicode="&amp;#x1f44f;"/> <emoji name="clap" unicode="&amp;#x1f44f;"/> from "clap"<linebreak/>
  <emoji name="clapper" unicode="&amp;#x1f3ac;"/> <emoji name="clapper" unicode="&amp;#x1f3ac;"/> from "clapper"<linebreak/>
  <emoji name="classical_building" unicode="&amp;#x1f3db;"/> <emoji name="classical_building" unicode="&amp;#x1f3db;"/> from "classical_building"<linebreak/>
+ <emoji name="climbing" unicode="&amp;#x1f9d7;"/> <emoji name="climbing" unicode="&amp;#x1f9d7;"/> from "climbing"<linebreak/>
+ <emoji name="climbing_man" unicode="&amp;#x1f9d7;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="climbing_man" unicode="&amp;#x1f9d7;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "climbing_man"<linebreak/>
+ <emoji name="climbing_woman" unicode="&amp;#x1f9d7;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="climbing_woman" unicode="&amp;#x1f9d7;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "climbing_woman"<linebreak/>
  <emoji name="clinking_glasses" unicode="&amp;#x1f942;"/> <emoji name="clinking_glasses" unicode="&amp;#x1f942;"/> from "clinking_glasses"<linebreak/>
  <emoji name="clipboard" unicode="&amp;#x1f4cb;"/> <emoji name="clipboard" unicode="&amp;#x1f4cb;"/> from "clipboard"<linebreak/>
+ <emoji name="clipperton_island" unicode="&amp;#x1f1e8;&amp;#x1f1f5;"/> <emoji name="clipperton_island" unicode="&amp;#x1f1e8;&amp;#x1f1f5;"/> from "clipperton_island"<linebreak/>
  <emoji name="clock1" unicode="&amp;#x1f550;"/> <emoji name="clock1" unicode="&amp;#x1f550;"/> from "clock1"<linebreak/>
  <emoji name="clock10" unicode="&amp;#x1f559;"/> <emoji name="clock10" unicode="&amp;#x1f559;"/> from "clock10"<linebreak/>
  <emoji name="clock1030" unicode="&amp;#x1f565;"/> <emoji name="clock1030" unicode="&amp;#x1f565;"/> from "clock1030"<linebreak/>
  <emoji name="clown_face" unicode="&amp;#x1f921;"/> <emoji name="clown_face" unicode="&amp;#x1f921;"/> from "clown_face"<linebreak/>
  <emoji name="clubs" unicode="&amp;#x2663;"/> <emoji name="clubs" unicode="&amp;#x2663;"/> from "clubs"<linebreak/>
  <emoji name="cn" unicode="&amp;#x1f1e8;&amp;#x1f1f3;"/> <emoji name="cn" unicode="&amp;#x1f1e8;&amp;#x1f1f3;"/> from "cn"<linebreak/>
+ <emoji name="coat" unicode="&amp;#x1f9e5;"/> <emoji name="coat" unicode="&amp;#x1f9e5;"/> from "coat"<linebreak/>
+ <emoji name="cockroach" unicode="&amp;#x1fab3;"/> <emoji name="cockroach" unicode="&amp;#x1fab3;"/> from "cockroach"<linebreak/>
  <emoji name="cocktail" unicode="&amp;#x1f378;"/> <emoji name="cocktail" unicode="&amp;#x1f378;"/> from "cocktail"<linebreak/>
+ <emoji name="coconut" unicode="&amp;#x1f965;"/> <emoji name="coconut" unicode="&amp;#x1f965;"/> from "coconut"<linebreak/>
  <emoji name="cocos_islands" unicode="&amp;#x1f1e8;&amp;#x1f1e8;"/> <emoji name="cocos_islands" unicode="&amp;#x1f1e8;&amp;#x1f1e8;"/> from "cocos_islands"<linebreak/>
  <emoji name="coffee" unicode="&amp;#x2615;"/> <emoji name="coffee" unicode="&amp;#x2615;"/> from "coffee"<linebreak/>
  <emoji name="coffin" unicode="&amp;#x26b0;"/> <emoji name="coffin" unicode="&amp;#x26b0;"/> from "coffin"<linebreak/>
+ <emoji name="coin" unicode="&amp;#x1fa99;"/> <emoji name="coin" unicode="&amp;#x1fa99;"/> from "coin"<linebreak/>
+ <emoji name="cold_face" unicode="&amp;#x1f976;"/> <emoji name="cold_face" unicode="&amp;#x1f976;"/> from "cold_face"<linebreak/>
  <emoji name="cold_sweat" unicode="&amp;#x1f630;"/> <emoji name="cold_sweat" unicode="&amp;#x1f630;"/> from "cold_sweat"<linebreak/>
  <emoji name="collision" unicode="&amp;#x1f4a5;"/> <emoji name="collision" unicode="&amp;#x1f4a5;"/> from "collision"<linebreak/>
  <emoji name="colombia" unicode="&amp;#x1f1e8;&amp;#x1f1f4;"/> <emoji name="colombia" unicode="&amp;#x1f1e8;&amp;#x1f1f4;"/> from "colombia"<linebreak/>
  <emoji name="comet" unicode="&amp;#x2604;"/> <emoji name="comet" unicode="&amp;#x2604;"/> from "comet"<linebreak/>
  <emoji name="comoros" unicode="&amp;#x1f1f0;&amp;#x1f1f2;"/> <emoji name="comoros" unicode="&amp;#x1f1f0;&amp;#x1f1f2;"/> from "comoros"<linebreak/>
+ <emoji name="compass" unicode="&amp;#x1f9ed;"/> <emoji name="compass" unicode="&amp;#x1f9ed;"/> from "compass"<linebreak/>
  <emoji name="computer" unicode="&amp;#x1f4bb;"/> <emoji name="computer" unicode="&amp;#x1f4bb;"/> from "computer"<linebreak/>
  <emoji name="computer_mouse" unicode="&amp;#x1f5b1;"/> <emoji name="computer_mouse" unicode="&amp;#x1f5b1;"/> from "computer_mouse"<linebreak/>
  <emoji name="confetti_ball" unicode="&amp;#x1f38a;"/> <emoji name="confetti_ball" unicode="&amp;#x1f38a;"/> from "confetti_ball"<linebreak/>
  <emoji name="congratulations" unicode="&amp;#x3297;"/> <emoji name="congratulations" unicode="&amp;#x3297;"/> from "congratulations"<linebreak/>
  <emoji name="construction" unicode="&amp;#x1f6a7;"/> <emoji name="construction" unicode="&amp;#x1f6a7;"/> from "construction"<linebreak/>
  <emoji name="construction_worker" unicode="&amp;#x1f477;"/> <emoji name="construction_worker" unicode="&amp;#x1f477;"/> from "construction_worker"<linebreak/>
- <emoji name="construction_worker_man" unicode="&amp;#x1f477;"/> <emoji name="construction_worker_man" unicode="&amp;#x1f477;"/> from "construction_worker_man"<linebreak/>
- <emoji name="construction_worker_woman" unicode="&amp;#x1f477;&amp;#x2640;"/> <emoji name="construction_worker_woman" unicode="&amp;#x1f477;&amp;#x2640;"/> from "construction_worker_woman"<linebreak/>
+ <emoji name="construction_worker_man" unicode="&amp;#x1f477;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="construction_worker_man" unicode="&amp;#x1f477;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "construction_worker_man"<linebreak/>
+ <emoji name="construction_worker_woman" unicode="&amp;#x1f477;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="construction_worker_woman" unicode="&amp;#x1f477;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "construction_worker_woman"<linebreak/>
  <emoji name="control_knobs" unicode="&amp;#x1f39b;"/> <emoji name="control_knobs" unicode="&amp;#x1f39b;"/> from "control_knobs"<linebreak/>
  <emoji name="convenience_store" unicode="&amp;#x1f3ea;"/> <emoji name="convenience_store" unicode="&amp;#x1f3ea;"/> from "convenience_store"<linebreak/>
+ <emoji name="cook" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f373;"/> <emoji name="cook" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f373;"/> from "cook"<linebreak/>
  <emoji name="cook_islands" unicode="&amp;#x1f1e8;&amp;#x1f1f0;"/> <emoji name="cook_islands" unicode="&amp;#x1f1e8;&amp;#x1f1f0;"/> from "cook_islands"<linebreak/>
  <emoji name="cookie" unicode="&amp;#x1f36a;"/> <emoji name="cookie" unicode="&amp;#x1f36a;"/> from "cookie"<linebreak/>
  <emoji name="cool" unicode="&amp;#x1f192;"/> <emoji name="cool" unicode="&amp;#x1f192;"/> from "cool"<linebreak/>
  <emoji name="couch_and_lamp" unicode="&amp;#x1f6cb;"/> <emoji name="couch_and_lamp" unicode="&amp;#x1f6cb;"/> from "couch_and_lamp"<linebreak/>
  <emoji name="couple" unicode="&amp;#x1f46b;"/> <emoji name="couple" unicode="&amp;#x1f46b;"/> from "couple"<linebreak/>
  <emoji name="couple_with_heart" unicode="&amp;#x1f491;"/> <emoji name="couple_with_heart" unicode="&amp;#x1f491;"/> from "couple_with_heart"<linebreak/>
- <emoji name="couple_with_heart_man_man" unicode="&amp;#x1f468;&amp;#x2764;&amp;#x1f468;"/> <emoji name="couple_with_heart_man_man" unicode="&amp;#x1f468;&amp;#x2764;&amp;#x1f468;"/> from "couple_with_heart_man_man"<linebreak/>
- <emoji name="couple_with_heart_woman_man" unicode="&amp;#x1f491;"/> <emoji name="couple_with_heart_woman_man" unicode="&amp;#x1f491;"/> from "couple_with_heart_woman_man"<linebreak/>
- <emoji name="couple_with_heart_woman_woman" unicode="&amp;#x1f469;&amp;#x2764;&amp;#x1f469;"/> <emoji name="couple_with_heart_woman_woman" unicode="&amp;#x1f469;&amp;#x2764;&amp;#x1f469;"/> from "couple_with_heart_woman_woman"<linebreak/>
- <emoji name="couplekiss_man_man" unicode="&amp;#x1f468;&amp;#x2764;&amp;#x1f48b;&amp;#x1f468;"/> <emoji name="couplekiss_man_man" unicode="&amp;#x1f468;&amp;#x2764;&amp;#x1f48b;&amp;#x1f468;"/> from "couplekiss_man_man"<linebreak/>
- <emoji name="couplekiss_man_woman" unicode="&amp;#x1f48f;"/> <emoji name="couplekiss_man_woman" unicode="&amp;#x1f48f;"/> from "couplekiss_man_woman"<linebreak/>
- <emoji name="couplekiss_woman_woman" unicode="&amp;#x1f469;&amp;#x2764;&amp;#x1f48b;&amp;#x1f469;"/> <emoji name="couplekiss_woman_woman" unicode="&amp;#x1f469;&amp;#x2764;&amp;#x1f48b;&amp;#x1f469;"/> from "couplekiss_woman_woman"<linebreak/>
+ <emoji name="couple_with_heart_man_man" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f48b;&amp;#x200d;&amp;#x1f468;"/> <emoji name="couple_with_heart_man_man" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f48b;&amp;#x200d;&amp;#x1f468;"/> from "couple_with_heart_man_man"<linebreak/>
+ <emoji name="couple_with_heart_woman_man" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f48b;&amp;#x200d;&amp;#x1f468;"/> <emoji name="couple_with_heart_woman_man" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f48b;&amp;#x200d;&amp;#x1f468;"/> from "couple_with_heart_woman_man"<linebreak/>
+ <emoji name="couple_with_heart_woman_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f48b;&amp;#x200d;&amp;#x1f469;"/> <emoji name="couple_with_heart_woman_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f48b;&amp;#x200d;&amp;#x1f469;"/> from "couple_with_heart_woman_woman"<linebreak/>
+ <emoji name="couplekiss" unicode="&amp;#x1f48f;"/> <emoji name="couplekiss" unicode="&amp;#x1f48f;"/> from "couplekiss"<linebreak/>
+ <emoji name="couplekiss_man_man" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f48b;&amp;#x200d;&amp;#x1f468;"/> <emoji name="couplekiss_man_man" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f48b;&amp;#x200d;&amp;#x1f468;"/> from "couplekiss_man_man"<linebreak/>
+ <emoji name="couplekiss_man_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f48b;&amp;#x200d;&amp;#x1f468;"/> <emoji name="couplekiss_man_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f48b;&amp;#x200d;&amp;#x1f468;"/> from "couplekiss_man_woman"<linebreak/>
+ <emoji name="couplekiss_woman_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f48b;&amp;#x200d;&amp;#x1f469;"/> <emoji name="couplekiss_woman_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f48b;&amp;#x200d;&amp;#x1f469;"/> from "couplekiss_woman_woman"<linebreak/>
  <emoji name="cow" unicode="&amp;#x1f42e;"/> <emoji name="cow" unicode="&amp;#x1f42e;"/> from "cow"<linebreak/>
  <emoji name="cow2" unicode="&amp;#x1f404;"/> <emoji name="cow2" unicode="&amp;#x1f404;"/> from "cow2"<linebreak/>
  <emoji name="cowboy_hat_face" unicode="&amp;#x1f920;"/> <emoji name="cowboy_hat_face" unicode="&amp;#x1f920;"/> from "cowboy_hat_face"<linebreak/>
  <emoji name="crayon" unicode="&amp;#x1f58d;"/> <emoji name="crayon" unicode="&amp;#x1f58d;"/> from "crayon"<linebreak/>
  <emoji name="credit_card" unicode="&amp;#x1f4b3;"/> <emoji name="credit_card" unicode="&amp;#x1f4b3;"/> from "credit_card"<linebreak/>
  <emoji name="crescent_moon" unicode="&amp;#x1f319;"/> <emoji name="crescent_moon" unicode="&amp;#x1f319;"/> from "crescent_moon"<linebreak/>
- <emoji name="cricket" unicode="&amp;#x1f3cf;"/> <emoji name="cricket" unicode="&amp;#x1f3cf;"/> from "cricket"<linebreak/>
+ <emoji name="cricket" unicode="&amp;#x1f997;"/> <emoji name="cricket" unicode="&amp;#x1f997;"/> from "cricket"<linebreak/>
+ <emoji name="cricket_game" unicode="&amp;#x1f3cf;"/> <emoji name="cricket_game" unicode="&amp;#x1f3cf;"/> from "cricket_game"<linebreak/>
  <emoji name="croatia" unicode="&amp;#x1f1ed;&amp;#x1f1f7;"/> <emoji name="croatia" unicode="&amp;#x1f1ed;&amp;#x1f1f7;"/> from "croatia"<linebreak/>
  <emoji name="crocodile" unicode="&amp;#x1f40a;"/> <emoji name="crocodile" unicode="&amp;#x1f40a;"/> from "crocodile"<linebreak/>
  <emoji name="croissant" unicode="&amp;#x1f950;"/> <emoji name="croissant" unicode="&amp;#x1f950;"/> from "croissant"<linebreak/>
  <emoji name="crystal_ball" unicode="&amp;#x1f52e;"/> <emoji name="crystal_ball" unicode="&amp;#x1f52e;"/> from "crystal_ball"<linebreak/>
  <emoji name="cuba" unicode="&amp;#x1f1e8;&amp;#x1f1fa;"/> <emoji name="cuba" unicode="&amp;#x1f1e8;&amp;#x1f1fa;"/> from "cuba"<linebreak/>
  <emoji name="cucumber" unicode="&amp;#x1f952;"/> <emoji name="cucumber" unicode="&amp;#x1f952;"/> from "cucumber"<linebreak/>
+ <emoji name="cup_with_straw" unicode="&amp;#x1f964;"/> <emoji name="cup_with_straw" unicode="&amp;#x1f964;"/> from "cup_with_straw"<linebreak/>
+ <emoji name="cupcake" unicode="&amp;#x1f9c1;"/> <emoji name="cupcake" unicode="&amp;#x1f9c1;"/> from "cupcake"<linebreak/>
  <emoji name="cupid" unicode="&amp;#x1f498;"/> <emoji name="cupid" unicode="&amp;#x1f498;"/> from "cupid"<linebreak/>
  <emoji name="curacao" unicode="&amp;#x1f1e8;&amp;#x1f1fc;"/> <emoji name="curacao" unicode="&amp;#x1f1e8;&amp;#x1f1fc;"/> from "curacao"<linebreak/>
+ <emoji name="curling_stone" unicode="&amp;#x1f94c;"/> <emoji name="curling_stone" unicode="&amp;#x1f94c;"/> from "curling_stone"<linebreak/>
+ <emoji name="curly_haired_man" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9b1;"/> <emoji name="curly_haired_man" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9b1;"/> from "curly_haired_man"<linebreak/>
+ <emoji name="curly_haired_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9b1;"/> <emoji name="curly_haired_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9b1;"/> from "curly_haired_woman"<linebreak/>
  <emoji name="curly_loop" unicode="&amp;#x27b0;"/> <emoji name="curly_loop" unicode="&amp;#x27b0;"/> from "curly_loop"<linebreak/>
  <emoji name="currency_exchange" unicode="&amp;#x1f4b1;"/> <emoji name="currency_exchange" unicode="&amp;#x1f4b1;"/> from "currency_exchange"<linebreak/>
  <emoji name="curry" unicode="&amp;#x1f35b;"/> <emoji name="curry" unicode="&amp;#x1f35b;"/> from "curry"<linebreak/>
+ <emoji name="cursing_face" unicode="&amp;#x1f92c;"/> <emoji name="cursing_face" unicode="&amp;#x1f92c;"/> from "cursing_face"<linebreak/>
  <emoji name="custard" unicode="&amp;#x1f36e;"/> <emoji name="custard" unicode="&amp;#x1f36e;"/> from "custard"<linebreak/>
  <emoji name="customs" unicode="&amp;#x1f6c3;"/> <emoji name="customs" unicode="&amp;#x1f6c3;"/> from "customs"<linebreak/>
+ <emoji name="cut_of_meat" unicode="&amp;#x1f969;"/> <emoji name="cut_of_meat" unicode="&amp;#x1f969;"/> from "cut_of_meat"<linebreak/>
  <emoji name="cyclone" unicode="&amp;#x1f300;"/> <emoji name="cyclone" unicode="&amp;#x1f300;"/> from "cyclone"<linebreak/>
  <emoji name="cyprus" unicode="&amp;#x1f1e8;&amp;#x1f1fe;"/> <emoji name="cyprus" unicode="&amp;#x1f1e8;&amp;#x1f1fe;"/> from "cyprus"<linebreak/>
  <emoji name="czech_republic" unicode="&amp;#x1f1e8;&amp;#x1f1ff;"/> <emoji name="czech_republic" unicode="&amp;#x1f1e8;&amp;#x1f1ff;"/> from "czech_republic"<linebreak/>
  <emoji name="dagger" unicode="&amp;#x1f5e1;"/> <emoji name="dagger" unicode="&amp;#x1f5e1;"/> from "dagger"<linebreak/>
  <emoji name="dancer" unicode="&amp;#x1f483;"/> <emoji name="dancer" unicode="&amp;#x1f483;"/> from "dancer"<linebreak/>
  <emoji name="dancers" unicode="&amp;#x1f46f;"/> <emoji name="dancers" unicode="&amp;#x1f46f;"/> from "dancers"<linebreak/>
- <emoji name="dancing_men" unicode="&amp;#x1f46f;&amp;#x2642;"/> <emoji name="dancing_men" unicode="&amp;#x1f46f;&amp;#x2642;"/> from "dancing_men"<linebreak/>
- <emoji name="dancing_women" unicode="&amp;#x1f46f;"/> <emoji name="dancing_women" unicode="&amp;#x1f46f;"/> from "dancing_women"<linebreak/>
+ <emoji name="dancing_men" unicode="&amp;#x1f46f;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="dancing_men" unicode="&amp;#x1f46f;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "dancing_men"<linebreak/>
+ <emoji name="dancing_women" unicode="&amp;#x1f46f;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="dancing_women" unicode="&amp;#x1f46f;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "dancing_women"<linebreak/>
  <emoji name="dango" unicode="&amp;#x1f361;"/> <emoji name="dango" unicode="&amp;#x1f361;"/> from "dango"<linebreak/>
  <emoji name="dark_sunglasses" unicode="&amp;#x1f576;"/> <emoji name="dark_sunglasses" unicode="&amp;#x1f576;"/> from "dark_sunglasses"<linebreak/>
  <emoji name="dart" unicode="&amp;#x1f3af;"/> <emoji name="dart" unicode="&amp;#x1f3af;"/> from "dart"<linebreak/>
  <emoji name="dash" unicode="&amp;#x1f4a8;"/> <emoji name="dash" unicode="&amp;#x1f4a8;"/> from "dash"<linebreak/>
  <emoji name="date" unicode="&amp;#x1f4c5;"/> <emoji name="date" unicode="&amp;#x1f4c5;"/> from "date"<linebreak/>
  <emoji name="de" unicode="&amp;#x1f1e9;&amp;#x1f1ea;"/> <emoji name="de" unicode="&amp;#x1f1e9;&amp;#x1f1ea;"/> from "de"<linebreak/>
+ <emoji name="deaf_man" unicode="&amp;#x1f9cf;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="deaf_man" unicode="&amp;#x1f9cf;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "deaf_man"<linebreak/>
+ <emoji name="deaf_person" unicode="&amp;#x1f9cf;"/> <emoji name="deaf_person" unicode="&amp;#x1f9cf;"/> from "deaf_person"<linebreak/>
+ <emoji name="deaf_woman" unicode="&amp;#x1f9cf;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="deaf_woman" unicode="&amp;#x1f9cf;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "deaf_woman"<linebreak/>
  <emoji name="deciduous_tree" unicode="&amp;#x1f333;"/> <emoji name="deciduous_tree" unicode="&amp;#x1f333;"/> from "deciduous_tree"<linebreak/>
  <emoji name="deer" unicode="&amp;#x1f98c;"/> <emoji name="deer" unicode="&amp;#x1f98c;"/> from "deer"<linebreak/>
  <emoji name="denmark" unicode="&amp;#x1f1e9;&amp;#x1f1f0;"/> <emoji name="denmark" unicode="&amp;#x1f1e9;&amp;#x1f1f0;"/> from "denmark"<linebreak/>
  <emoji name="detective" unicode="&amp;#x1f575;"/> <emoji name="detective" unicode="&amp;#x1f575;"/> from "detective"<linebreak/>
  <emoji name="diamond_shape_with_a_dot_inside" unicode="&amp;#x1f4a0;"/> <emoji name="diamond_shape_with_a_dot_inside" unicode="&amp;#x1f4a0;"/> from "diamond_shape_with_a_dot_inside"<linebreak/>
  <emoji name="diamonds" unicode="&amp;#x2666;"/> <emoji name="diamonds" unicode="&amp;#x2666;"/> from "diamonds"<linebreak/>
+ <emoji name="diego_garcia" unicode="&amp;#x1f1e9;&amp;#x1f1ec;"/> <emoji name="diego_garcia" unicode="&amp;#x1f1e9;&amp;#x1f1ec;"/> from "diego_garcia"<linebreak/>
  <emoji name="disappointed" unicode="&amp;#x1f61e;"/> <emoji name="disappointed" unicode="&amp;#x1f61e;"/> from "disappointed"<linebreak/>
  <emoji name="disappointed_relieved" unicode="&amp;#x1f625;"/> <emoji name="disappointed_relieved" unicode="&amp;#x1f625;"/> from "disappointed_relieved"<linebreak/>
+ <emoji name="disguised_face" unicode="&amp;#x1f978;"/> <emoji name="disguised_face" unicode="&amp;#x1f978;"/> from "disguised_face"<linebreak/>
+ <emoji name="diving_mask" unicode="&amp;#x1f93f;"/> <emoji name="diving_mask" unicode="&amp;#x1f93f;"/> from "diving_mask"<linebreak/>
+ <emoji name="diya_lamp" unicode="&amp;#x1fa94;"/> <emoji name="diya_lamp" unicode="&amp;#x1fa94;"/> from "diya_lamp"<linebreak/>
  <emoji name="dizzy" unicode="&amp;#x1f4ab;"/> <emoji name="dizzy" unicode="&amp;#x1f4ab;"/> from "dizzy"<linebreak/>
  <emoji name="dizzy_face" unicode="&amp;#x1f635;"/> <emoji name="dizzy_face" unicode="&amp;#x1f635;"/> from "dizzy_face"<linebreak/>
  <emoji name="djibouti" unicode="&amp;#x1f1e9;&amp;#x1f1ef;"/> <emoji name="djibouti" unicode="&amp;#x1f1e9;&amp;#x1f1ef;"/> from "djibouti"<linebreak/>
+ <emoji name="dna" unicode="&amp;#x1f9ec;"/> <emoji name="dna" unicode="&amp;#x1f9ec;"/> from "dna"<linebreak/>
  <emoji name="do_not_litter" unicode="&amp;#x1f6af;"/> <emoji name="do_not_litter" unicode="&amp;#x1f6af;"/> from "do_not_litter"<linebreak/>
+ <emoji name="dodo" unicode="&amp;#x1f9a4;"/> <emoji name="dodo" unicode="&amp;#x1f9a4;"/> from "dodo"<linebreak/>
  <emoji name="dog" unicode="&amp;#x1f436;"/> <emoji name="dog" unicode="&amp;#x1f436;"/> from "dog"<linebreak/>
  <emoji name="dog2" unicode="&amp;#x1f415;"/> <emoji name="dog2" unicode="&amp;#x1f415;"/> from "dog2"<linebreak/>
  <emoji name="dollar" unicode="&amp;#x1f4b5;"/> <emoji name="dollar" unicode="&amp;#x1f4b5;"/> from "dollar"<linebreak/>
  <emoji name="dress" unicode="&amp;#x1f457;"/> <emoji name="dress" unicode="&amp;#x1f457;"/> from "dress"<linebreak/>
  <emoji name="dromedary_camel" unicode="&amp;#x1f42a;"/> <emoji name="dromedary_camel" unicode="&amp;#x1f42a;"/> from "dromedary_camel"<linebreak/>
  <emoji name="drooling_face" unicode="&amp;#x1f924;"/> <emoji name="drooling_face" unicode="&amp;#x1f924;"/> from "drooling_face"<linebreak/>
+ <emoji name="drop_of_blood" unicode="&amp;#x1fa78;"/> <emoji name="drop_of_blood" unicode="&amp;#x1fa78;"/> from "drop_of_blood"<linebreak/>
  <emoji name="droplet" unicode="&amp;#x1f4a7;"/> <emoji name="droplet" unicode="&amp;#x1f4a7;"/> from "droplet"<linebreak/>
  <emoji name="drum" unicode="&amp;#x1f941;"/> <emoji name="drum" unicode="&amp;#x1f941;"/> from "drum"<linebreak/>
  <emoji name="duck" unicode="&amp;#x1f986;"/> <emoji name="duck" unicode="&amp;#x1f986;"/> from "duck"<linebreak/>
+ <emoji name="dumpling" unicode="&amp;#x1f95f;"/> <emoji name="dumpling" unicode="&amp;#x1f95f;"/> from "dumpling"<linebreak/>
  <emoji name="dvd" unicode="&amp;#x1f4c0;"/> <emoji name="dvd" unicode="&amp;#x1f4c0;"/> from "dvd"<linebreak/>
  <emoji name="e-mail" unicode="&amp;#x1f4e7;"/> <emoji name="e-mail" unicode="&amp;#x1f4e7;"/> from "e-mail"<linebreak/>
  <emoji name="eagle" unicode="&amp;#x1f985;"/> <emoji name="eagle" unicode="&amp;#x1f985;"/> from "eagle"<linebreak/>
  <emoji name="ear" unicode="&amp;#x1f442;"/> <emoji name="ear" unicode="&amp;#x1f442;"/> from "ear"<linebreak/>
  <emoji name="ear_of_rice" unicode="&amp;#x1f33e;"/> <emoji name="ear_of_rice" unicode="&amp;#x1f33e;"/> from "ear_of_rice"<linebreak/>
+ <emoji name="ear_with_hearing_aid" unicode="&amp;#x1f9bb;"/> <emoji name="ear_with_hearing_aid" unicode="&amp;#x1f9bb;"/> from "ear_with_hearing_aid"<linebreak/>
  <emoji name="earth_africa" unicode="&amp;#x1f30d;"/> <emoji name="earth_africa" unicode="&amp;#x1f30d;"/> from "earth_africa"<linebreak/>
  <emoji name="earth_americas" unicode="&amp;#x1f30e;"/> <emoji name="earth_americas" unicode="&amp;#x1f30e;"/> from "earth_americas"<linebreak/>
  <emoji name="earth_asia" unicode="&amp;#x1f30f;"/> <emoji name="earth_asia" unicode="&amp;#x1f30f;"/> from "earth_asia"<linebreak/>
  <emoji name="egg" unicode="&amp;#x1f95a;"/> <emoji name="egg" unicode="&amp;#x1f95a;"/> from "egg"<linebreak/>
  <emoji name="eggplant" unicode="&amp;#x1f346;"/> <emoji name="eggplant" unicode="&amp;#x1f346;"/> from "eggplant"<linebreak/>
  <emoji name="egypt" unicode="&amp;#x1f1ea;&amp;#x1f1ec;"/> <emoji name="egypt" unicode="&amp;#x1f1ea;&amp;#x1f1ec;"/> from "egypt"<linebreak/>
- <emoji name="eight" unicode="&amp;#x0038;&amp;#x20e3;"/> <emoji name="eight" unicode="&amp;#x0038;&amp;#x20e3;"/> from "eight"<linebreak/>
+ <emoji name="eight" unicode="&amp;#x0038;&amp;#xfe0f;&amp;#x20e3;"/> <emoji name="eight" unicode="&amp;#x0038;&amp;#xfe0f;&amp;#x20e3;"/> from "eight"<linebreak/>
  <emoji name="eight_pointed_black_star" unicode="&amp;#x2734;"/> <emoji name="eight_pointed_black_star" unicode="&amp;#x2734;"/> from "eight_pointed_black_star"<linebreak/>
  <emoji name="eight_spoked_asterisk" unicode="&amp;#x2733;"/> <emoji name="eight_spoked_asterisk" unicode="&amp;#x2733;"/> from "eight_spoked_asterisk"<linebreak/>
+ <emoji name="eject_button" unicode="&amp;#x23cf;"/> <emoji name="eject_button" unicode="&amp;#x23cf;"/> from "eject_button"<linebreak/>
  <emoji name="el_salvador" unicode="&amp;#x1f1f8;&amp;#x1f1fb;"/> <emoji name="el_salvador" unicode="&amp;#x1f1f8;&amp;#x1f1fb;"/> from "el_salvador"<linebreak/>
  <emoji name="electric_plug" unicode="&amp;#x1f50c;"/> <emoji name="electric_plug" unicode="&amp;#x1f50c;"/> from "electric_plug"<linebreak/>
  <emoji name="elephant" unicode="&amp;#x1f418;"/> <emoji name="elephant" unicode="&amp;#x1f418;"/> from "elephant"<linebreak/>
- <emoji name="email" unicode="&amp;#x2709;"/> <emoji name="email" unicode="&amp;#x2709;"/> from "email"<linebreak/>
+ <emoji name="elevator" unicode="&amp;#x1f6d7;"/> <emoji name="elevator" unicode="&amp;#x1f6d7;"/> from "elevator"<linebreak/>
+ <emoji name="elf" unicode="&amp;#x1f9dd;"/> <emoji name="elf" unicode="&amp;#x1f9dd;"/> from "elf"<linebreak/>
+ <emoji name="elf_man" unicode="&amp;#x1f9dd;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="elf_man" unicode="&amp;#x1f9dd;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "elf_man"<linebreak/>
+ <emoji name="elf_woman" unicode="&amp;#x1f9dd;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="elf_woman" unicode="&amp;#x1f9dd;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "elf_woman"<linebreak/>
+ <emoji name="email" unicode="&amp;#x1f4e7;"/> <emoji name="email" unicode="&amp;#x1f4e7;"/> from "email"<linebreak/>
  <emoji name="end" unicode="&amp;#x1f51a;"/> <emoji name="end" unicode="&amp;#x1f51a;"/> from "end"<linebreak/>
+ <emoji name="england" unicode="&amp;#x1f3f4;&amp;#xe0067;&amp;#xe0062;&amp;#xe0065;&amp;#xe006e;&amp;#xe0067;&amp;#xe007f;"/> <emoji name="england" unicode="&amp;#x1f3f4;&amp;#xe0067;&amp;#xe0062;&amp;#xe0065;&amp;#xe006e;&amp;#xe0067;&amp;#xe007f;"/> from "england"<linebreak/>
  <emoji name="envelope" unicode="&amp;#x2709;"/> <emoji name="envelope" unicode="&amp;#x2709;"/> from "envelope"<linebreak/>
  <emoji name="envelope_with_arrow" unicode="&amp;#x1f4e9;"/> <emoji name="envelope_with_arrow" unicode="&amp;#x1f4e9;"/> from "envelope_with_arrow"<linebreak/>
  <emoji name="equatorial_guinea" unicode="&amp;#x1f1ec;&amp;#x1f1f6;"/> <emoji name="equatorial_guinea" unicode="&amp;#x1f1ec;&amp;#x1f1f6;"/> from "equatorial_guinea"<linebreak/>
  <emoji name="european_union" unicode="&amp;#x1f1ea;&amp;#x1f1fa;"/> <emoji name="european_union" unicode="&amp;#x1f1ea;&amp;#x1f1fa;"/> from "european_union"<linebreak/>
  <emoji name="evergreen_tree" unicode="&amp;#x1f332;"/> <emoji name="evergreen_tree" unicode="&amp;#x1f332;"/> from "evergreen_tree"<linebreak/>
  <emoji name="exclamation" unicode="&amp;#x2757;"/> <emoji name="exclamation" unicode="&amp;#x2757;"/> from "exclamation"<linebreak/>
+ <emoji name="exploding_head" unicode="&amp;#x1f92f;"/> <emoji name="exploding_head" unicode="&amp;#x1f92f;"/> from "exploding_head"<linebreak/>
  <emoji name="expressionless" unicode="&amp;#x1f611;"/> <emoji name="expressionless" unicode="&amp;#x1f611;"/> from "expressionless"<linebreak/>
- <emoji name="eye" unicode="&amp;#x1f441;"/> <emoji name="eye" unicode="&amp;#x1f441;"/> from "eye"<linebreak/>
- <emoji name="eye_speech_bubble" unicode="&amp;#x1f441;&amp;#x1f5e8;"/> <emoji name="eye_speech_bubble" unicode="&amp;#x1f441;&amp;#x1f5e8;"/> from "eye_speech_bubble"<linebreak/>
+ <emoji name="eye" unicode="&amp;#x1f441;&amp;#xfe0f;&amp;#x200d;&amp;#x1f5e8;&amp;#xfe0f;"/> <emoji name="eye" unicode="&amp;#x1f441;&amp;#xfe0f;&amp;#x200d;&amp;#x1f5e8;&amp;#xfe0f;"/> from "eye"<linebreak/>
+ <emoji name="eye_speech_bubble" unicode="&amp;#x1f441;&amp;#xfe0f;&amp;#x200d;&amp;#x1f5e8;&amp;#xfe0f;"/> <emoji name="eye_speech_bubble" unicode="&amp;#x1f441;&amp;#xfe0f;&amp;#x200d;&amp;#x1f5e8;&amp;#xfe0f;"/> from "eye_speech_bubble"<linebreak/>
  <emoji name="eyeglasses" unicode="&amp;#x1f453;"/> <emoji name="eyeglasses" unicode="&amp;#x1f453;"/> from "eyeglasses"<linebreak/>
  <emoji name="eyes" unicode="&amp;#x1f440;"/> <emoji name="eyes" unicode="&amp;#x1f440;"/> from "eyes"<linebreak/>
+ <emoji name="face_exhaling" unicode="&amp;#x1f62e;&amp;#x200d;&amp;#x1f4a8;"/> <emoji name="face_exhaling" unicode="&amp;#x1f62e;&amp;#x200d;&amp;#x1f4a8;"/> from "face_exhaling"<linebreak/>
+ <emoji name="face_in_clouds" unicode="&amp;#x1f636;&amp;#x200d;&amp;#x1f32b;&amp;#xfe0f;"/> <emoji name="face_in_clouds" unicode="&amp;#x1f636;&amp;#x200d;&amp;#x1f32b;&amp;#xfe0f;"/> from "face_in_clouds"<linebreak/>
  <emoji name="face_with_head_bandage" unicode="&amp;#x1f915;"/> <emoji name="face_with_head_bandage" unicode="&amp;#x1f915;"/> from "face_with_head_bandage"<linebreak/>
+ <emoji name="face_with_spiral_eyes" unicode="&amp;#x1f635;&amp;#x200d;&amp;#x1f4ab;"/> <emoji name="face_with_spiral_eyes" unicode="&amp;#x1f635;&amp;#x200d;&amp;#x1f4ab;"/> from "face_with_spiral_eyes"<linebreak/>
  <emoji name="face_with_thermometer" unicode="&amp;#x1f912;"/> <emoji name="face_with_thermometer" unicode="&amp;#x1f912;"/> from "face_with_thermometer"<linebreak/>
+ <emoji name="facepalm" unicode="&amp;#x1f926;"/> <emoji name="facepalm" unicode="&amp;#x1f926;"/> from "facepalm"<linebreak/>
  <emoji name="facepunch" unicode="&amp;#x1f44a;"/> <emoji name="facepunch" unicode="&amp;#x1f44a;"/> from "facepunch"<linebreak/>
  <emoji name="factory" unicode="&amp;#x1f3ed;"/> <emoji name="factory" unicode="&amp;#x1f3ed;"/> from "factory"<linebreak/>
+ <emoji name="factory_worker" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f3ed;"/> <emoji name="factory_worker" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f3ed;"/> from "factory_worker"<linebreak/>
+ <emoji name="fairy" unicode="&amp;#x1f9da;"/> <emoji name="fairy" unicode="&amp;#x1f9da;"/> from "fairy"<linebreak/>
+ <emoji name="fairy_man" unicode="&amp;#x1f9da;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="fairy_man" unicode="&amp;#x1f9da;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "fairy_man"<linebreak/>
+ <emoji name="fairy_woman" unicode="&amp;#x1f9da;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="fairy_woman" unicode="&amp;#x1f9da;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "fairy_woman"<linebreak/>
+ <emoji name="falafel" unicode="&amp;#x1f9c6;"/> <emoji name="falafel" unicode="&amp;#x1f9c6;"/> from "falafel"<linebreak/>
  <emoji name="falkland_islands" unicode="&amp;#x1f1eb;&amp;#x1f1f0;"/> <emoji name="falkland_islands" unicode="&amp;#x1f1eb;&amp;#x1f1f0;"/> from "falkland_islands"<linebreak/>
  <emoji name="fallen_leaf" unicode="&amp;#x1f342;"/> <emoji name="fallen_leaf" unicode="&amp;#x1f342;"/> from "fallen_leaf"<linebreak/>
  <emoji name="family" unicode="&amp;#x1f46a;"/> <emoji name="family" unicode="&amp;#x1f46a;"/> from "family"<linebreak/>
- <emoji name="family_man_boy" unicode="&amp;#x1f468;&amp;#x1f466;"/> <emoji name="family_man_boy" unicode="&amp;#x1f468;&amp;#x1f466;"/> from "family_man_boy"<linebreak/>
- <emoji name="family_man_boy_boy" unicode="&amp;#x1f468;&amp;#x1f466;&amp;#x1f466;"/> <emoji name="family_man_boy_boy" unicode="&amp;#x1f468;&amp;#x1f466;&amp;#x1f466;"/> from "family_man_boy_boy"<linebreak/>
- <emoji name="family_man_girl" unicode="&amp;#x1f468;&amp;#x1f467;"/> <emoji name="family_man_girl" unicode="&amp;#x1f468;&amp;#x1f467;"/> from "family_man_girl"<linebreak/>
- <emoji name="family_man_girl_boy" unicode="&amp;#x1f468;&amp;#x1f467;&amp;#x1f466;"/> <emoji name="family_man_girl_boy" unicode="&amp;#x1f468;&amp;#x1f467;&amp;#x1f466;"/> from "family_man_girl_boy"<linebreak/>
- <emoji name="family_man_girl_girl" unicode="&amp;#x1f468;&amp;#x1f467;&amp;#x1f467;"/> <emoji name="family_man_girl_girl" unicode="&amp;#x1f468;&amp;#x1f467;&amp;#x1f467;"/> from "family_man_girl_girl"<linebreak/>
- <emoji name="family_man_man_boy" unicode="&amp;#x1f468;&amp;#x1f468;&amp;#x1f466;"/> <emoji name="family_man_man_boy" unicode="&amp;#x1f468;&amp;#x1f468;&amp;#x1f466;"/> from "family_man_man_boy"<linebreak/>
- <emoji name="family_man_man_boy_boy" unicode="&amp;#x1f468;&amp;#x1f468;&amp;#x1f466;&amp;#x1f466;"/> <emoji name="family_man_man_boy_boy" unicode="&amp;#x1f468;&amp;#x1f468;&amp;#x1f466;&amp;#x1f466;"/> from "family_man_man_boy_boy"<linebreak/>
- <emoji name="family_man_man_girl" unicode="&amp;#x1f468;&amp;#x1f468;&amp;#x1f467;"/> <emoji name="family_man_man_girl" unicode="&amp;#x1f468;&amp;#x1f468;&amp;#x1f467;"/> from "family_man_man_girl"<linebreak/>
- <emoji name="family_man_man_girl_boy" unicode="&amp;#x1f468;&amp;#x1f468;&amp;#x1f467;&amp;#x1f466;"/> <emoji name="family_man_man_girl_boy" unicode="&amp;#x1f468;&amp;#x1f468;&amp;#x1f467;&amp;#x1f466;"/> from "family_man_man_girl_boy"<linebreak/>
- <emoji name="family_man_man_girl_girl" unicode="&amp;#x1f468;&amp;#x1f468;&amp;#x1f467;&amp;#x1f467;"/> <emoji name="family_man_man_girl_girl" unicode="&amp;#x1f468;&amp;#x1f468;&amp;#x1f467;&amp;#x1f467;"/> from "family_man_man_girl_girl"<linebreak/>
- <emoji name="family_man_woman_boy" unicode="&amp;#x1f46a;"/> <emoji name="family_man_woman_boy" unicode="&amp;#x1f46a;"/> from "family_man_woman_boy"<linebreak/>
- <emoji name="family_man_woman_boy_boy" unicode="&amp;#x1f468;&amp;#x1f469;&amp;#x1f466;&amp;#x1f466;"/> <emoji name="family_man_woman_boy_boy" unicode="&amp;#x1f468;&amp;#x1f469;&amp;#x1f466;&amp;#x1f466;"/> from "family_man_woman_boy_boy"<linebreak/>
- <emoji name="family_man_woman_girl" unicode="&amp;#x1f468;&amp;#x1f469;&amp;#x1f467;"/> <emoji name="family_man_woman_girl" unicode="&amp;#x1f468;&amp;#x1f469;&amp;#x1f467;"/> from "family_man_woman_girl"<linebreak/>
- <emoji name="family_man_woman_girl_boy" unicode="&amp;#x1f468;&amp;#x1f469;&amp;#x1f467;&amp;#x1f466;"/> <emoji name="family_man_woman_girl_boy" unicode="&amp;#x1f468;&amp;#x1f469;&amp;#x1f467;&amp;#x1f466;"/> from "family_man_woman_girl_boy"<linebreak/>
- <emoji name="family_man_woman_girl_girl" unicode="&amp;#x1f468;&amp;#x1f469;&amp;#x1f467;&amp;#x1f467;"/> <emoji name="family_man_woman_girl_girl" unicode="&amp;#x1f468;&amp;#x1f469;&amp;#x1f467;&amp;#x1f467;"/> from "family_man_woman_girl_girl"<linebreak/>
- <emoji name="family_woman_boy" unicode="&amp;#x1f469;&amp;#x1f466;"/> <emoji name="family_woman_boy" unicode="&amp;#x1f469;&amp;#x1f466;"/> from "family_woman_boy"<linebreak/>
- <emoji name="family_woman_boy_boy" unicode="&amp;#x1f469;&amp;#x1f466;&amp;#x1f466;"/> <emoji name="family_woman_boy_boy" unicode="&amp;#x1f469;&amp;#x1f466;&amp;#x1f466;"/> from "family_woman_boy_boy"<linebreak/>
- <emoji name="family_woman_girl" unicode="&amp;#x1f469;&amp;#x1f467;"/> <emoji name="family_woman_girl" unicode="&amp;#x1f469;&amp;#x1f467;"/> from "family_woman_girl"<linebreak/>
- <emoji name="family_woman_girl_boy" unicode="&amp;#x1f469;&amp;#x1f467;&amp;#x1f466;"/> <emoji name="family_woman_girl_boy" unicode="&amp;#x1f469;&amp;#x1f467;&amp;#x1f466;"/> from "family_woman_girl_boy"<linebreak/>
- <emoji name="family_woman_girl_girl" unicode="&amp;#x1f469;&amp;#x1f467;&amp;#x1f467;"/> <emoji name="family_woman_girl_girl" unicode="&amp;#x1f469;&amp;#x1f467;&amp;#x1f467;"/> from "family_woman_girl_girl"<linebreak/>
- <emoji name="family_woman_woman_boy" unicode="&amp;#x1f469;&amp;#x1f469;&amp;#x1f466;"/> <emoji name="family_woman_woman_boy" unicode="&amp;#x1f469;&amp;#x1f469;&amp;#x1f466;"/> from "family_woman_woman_boy"<linebreak/>
- <emoji name="family_woman_woman_boy_boy" unicode="&amp;#x1f469;&amp;#x1f469;&amp;#x1f466;&amp;#x1f466;"/> <emoji name="family_woman_woman_boy_boy" unicode="&amp;#x1f469;&amp;#x1f469;&amp;#x1f466;&amp;#x1f466;"/> from "family_woman_woman_boy_boy"<linebreak/>
- <emoji name="family_woman_woman_girl" unicode="&amp;#x1f469;&amp;#x1f469;&amp;#x1f467;"/> <emoji name="family_woman_woman_girl" unicode="&amp;#x1f469;&amp;#x1f469;&amp;#x1f467;"/> from "family_woman_woman_girl"<linebreak/>
- <emoji name="family_woman_woman_girl_boy" unicode="&amp;#x1f469;&amp;#x1f469;&amp;#x1f467;&amp;#x1f466;"/> <emoji name="family_woman_woman_girl_boy" unicode="&amp;#x1f469;&amp;#x1f469;&amp;#x1f467;&amp;#x1f466;"/> from "family_woman_woman_girl_boy"<linebreak/>
- <emoji name="family_woman_woman_girl_girl" unicode="&amp;#x1f469;&amp;#x1f469;&amp;#x1f467;&amp;#x1f467;"/> <emoji name="family_woman_woman_girl_girl" unicode="&amp;#x1f469;&amp;#x1f469;&amp;#x1f467;&amp;#x1f467;"/> from "family_woman_woman_girl_girl"<linebreak/>
+ <emoji name="family_man_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_man_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;"/> from "family_man_boy"<linebreak/>
+ <emoji name="family_man_boy_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_man_boy_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;&amp;#x200d;&amp;#x1f466;"/> from "family_man_boy_boy"<linebreak/>
+ <emoji name="family_man_girl" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;"/> <emoji name="family_man_girl" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;"/> from "family_man_girl"<linebreak/>
+ <emoji name="family_man_girl_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_man_girl_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f466;"/> from "family_man_girl_boy"<linebreak/>
+ <emoji name="family_man_girl_girl" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f467;"/> <emoji name="family_man_girl_girl" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f467;"/> from "family_man_girl_girl"<linebreak/>
+ <emoji name="family_man_man_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f468;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_man_man_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f468;&amp;#x200d;&amp;#x1f466;"/> from "family_man_man_boy"<linebreak/>
+ <emoji name="family_man_man_boy_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f468;&amp;#x200d;&amp;#x1f466;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_man_man_boy_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f468;&amp;#x200d;&amp;#x1f466;&amp;#x200d;&amp;#x1f466;"/> from "family_man_man_boy_boy"<linebreak/>
+ <emoji name="family_man_man_girl" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f468;&amp;#x200d;&amp;#x1f467;"/> <emoji name="family_man_man_girl" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f468;&amp;#x200d;&amp;#x1f467;"/> from "family_man_man_girl"<linebreak/>
+ <emoji name="family_man_man_girl_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f468;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_man_man_girl_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f468;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f466;"/> from "family_man_man_girl_boy"<linebreak/>
+ <emoji name="family_man_man_girl_girl" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f468;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f467;"/> <emoji name="family_man_man_girl_girl" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f468;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f467;"/> from "family_man_man_girl_girl"<linebreak/>
+ <emoji name="family_man_woman_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_man_woman_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;"/> from "family_man_woman_boy"<linebreak/>
+ <emoji name="family_man_woman_boy_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_man_woman_boy_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;&amp;#x200d;&amp;#x1f466;"/> from "family_man_woman_boy_boy"<linebreak/>
+ <emoji name="family_man_woman_girl" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;"/> <emoji name="family_man_woman_girl" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;"/> from "family_man_woman_girl"<linebreak/>
+ <emoji name="family_man_woman_girl_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_man_woman_girl_boy" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f466;"/> from "family_man_woman_girl_boy"<linebreak/>
+ <emoji name="family_man_woman_girl_girl" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f467;"/> <emoji name="family_man_woman_girl_girl" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f467;"/> from "family_man_woman_girl_girl"<linebreak/>
+ <emoji name="family_woman_boy" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_woman_boy" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;"/> from "family_woman_boy"<linebreak/>
+ <emoji name="family_woman_boy_boy" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_woman_boy_boy" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;&amp;#x200d;&amp;#x1f466;"/> from "family_woman_boy_boy"<linebreak/>
+ <emoji name="family_woman_girl" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;"/> <emoji name="family_woman_girl" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;"/> from "family_woman_girl"<linebreak/>
+ <emoji name="family_woman_girl_boy" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_woman_girl_boy" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f466;"/> from "family_woman_girl_boy"<linebreak/>
+ <emoji name="family_woman_girl_girl" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f467;"/> <emoji name="family_woman_girl_girl" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f467;"/> from "family_woman_girl_girl"<linebreak/>
+ <emoji name="family_woman_woman_boy" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_woman_woman_boy" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;"/> from "family_woman_woman_boy"<linebreak/>
+ <emoji name="family_woman_woman_boy_boy" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_woman_woman_boy_boy" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f466;&amp;#x200d;&amp;#x1f466;"/> from "family_woman_woman_boy_boy"<linebreak/>
+ <emoji name="family_woman_woman_girl" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;"/> <emoji name="family_woman_woman_girl" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;"/> from "family_woman_woman_girl"<linebreak/>
+ <emoji name="family_woman_woman_girl_boy" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f466;"/> <emoji name="family_woman_woman_girl_boy" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f466;"/> from "family_woman_woman_girl_boy"<linebreak/>
+ <emoji name="family_woman_woman_girl_girl" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f467;"/> <emoji name="family_woman_woman_girl_girl" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f469;&amp;#x200d;&amp;#x1f467;&amp;#x200d;&amp;#x1f467;"/> from "family_woman_woman_girl_girl"<linebreak/>
+ <emoji name="farmer" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f33e;"/> <emoji name="farmer" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f33e;"/> from "farmer"<linebreak/>
  <emoji name="faroe_islands" unicode="&amp;#x1f1eb;&amp;#x1f1f4;"/> <emoji name="faroe_islands" unicode="&amp;#x1f1eb;&amp;#x1f1f4;"/> from "faroe_islands"<linebreak/>
  <emoji name="fast_forward" unicode="&amp;#x23e9;"/> <emoji name="fast_forward" unicode="&amp;#x23e9;"/> from "fast_forward"<linebreak/>
  <emoji name="fax" unicode="&amp;#x1f4e0;"/> <emoji name="fax" unicode="&amp;#x1f4e0;"/> from "fax"<linebreak/>
  <emoji name="fearful" unicode="&amp;#x1f628;"/> <emoji name="fearful" unicode="&amp;#x1f628;"/> from "fearful"<linebreak/>
+ <emoji name="feather" unicode="&amp;#x1fab6;"/> <emoji name="feather" unicode="&amp;#x1fab6;"/> from "feather"<linebreak/>
  <emoji name="feet" unicode="&amp;#x1f43e;"/> <emoji name="feet" unicode="&amp;#x1f43e;"/> from "feet"<linebreak/>
- <emoji name="female_detective" unicode="&amp;#x1f575;&amp;#x2640;"/> <emoji name="female_detective" unicode="&amp;#x1f575;&amp;#x2640;"/> from "female_detective"<linebreak/>
+ <emoji name="female_detective" unicode="&amp;#x1f575;&amp;#xfe0f;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="female_detective" unicode="&amp;#x1f575;&amp;#xfe0f;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "female_detective"<linebreak/>
+ <emoji name="female_sign" unicode="&amp;#x2640;"/> <emoji name="female_sign" unicode="&amp;#x2640;"/> from "female_sign"<linebreak/>
  <emoji name="ferris_wheel" unicode="&amp;#x1f3a1;"/> <emoji name="ferris_wheel" unicode="&amp;#x1f3a1;"/> from "ferris_wheel"<linebreak/>
  <emoji name="ferry" unicode="&amp;#x26f4;"/> <emoji name="ferry" unicode="&amp;#x26f4;"/> from "ferry"<linebreak/>
  <emoji name="field_hockey" unicode="&amp;#x1f3d1;"/> <emoji name="field_hockey" unicode="&amp;#x1f3d1;"/> from "field_hockey"<linebreak/>
  <emoji name="finland" unicode="&amp;#x1f1eb;&amp;#x1f1ee;"/> <emoji name="finland" unicode="&amp;#x1f1eb;&amp;#x1f1ee;"/> from "finland"<linebreak/>
  <emoji name="fire" unicode="&amp;#x1f525;"/> <emoji name="fire" unicode="&amp;#x1f525;"/> from "fire"<linebreak/>
  <emoji name="fire_engine" unicode="&amp;#x1f692;"/> <emoji name="fire_engine" unicode="&amp;#x1f692;"/> from "fire_engine"<linebreak/>
+ <emoji name="fire_extinguisher" unicode="&amp;#x1f9ef;"/> <emoji name="fire_extinguisher" unicode="&amp;#x1f9ef;"/> from "fire_extinguisher"<linebreak/>
+ <emoji name="firecracker" unicode="&amp;#x1f9e8;"/> <emoji name="firecracker" unicode="&amp;#x1f9e8;"/> from "firecracker"<linebreak/>
+ <emoji name="firefighter" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f692;"/> <emoji name="firefighter" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f692;"/> from "firefighter"<linebreak/>
  <emoji name="fireworks" unicode="&amp;#x1f386;"/> <emoji name="fireworks" unicode="&amp;#x1f386;"/> from "fireworks"<linebreak/>
  <emoji name="first_quarter_moon" unicode="&amp;#x1f313;"/> <emoji name="first_quarter_moon" unicode="&amp;#x1f313;"/> from "first_quarter_moon"<linebreak/>
  <emoji name="first_quarter_moon_with_face" unicode="&amp;#x1f31b;"/> <emoji name="first_quarter_moon_with_face" unicode="&amp;#x1f31b;"/> from "first_quarter_moon_with_face"<linebreak/>
  <emoji name="fist_oncoming" unicode="&amp;#x1f44a;"/> <emoji name="fist_oncoming" unicode="&amp;#x1f44a;"/> from "fist_oncoming"<linebreak/>
  <emoji name="fist_raised" unicode="&amp;#x270a;"/> <emoji name="fist_raised" unicode="&amp;#x270a;"/> from "fist_raised"<linebreak/>
  <emoji name="fist_right" unicode="&amp;#x1f91c;"/> <emoji name="fist_right" unicode="&amp;#x1f91c;"/> from "fist_right"<linebreak/>
- <emoji name="five" unicode="&amp;#x0035;&amp;#x20e3;"/> <emoji name="five" unicode="&amp;#x0035;&amp;#x20e3;"/> from "five"<linebreak/>
+ <emoji name="five" unicode="&amp;#x0035;&amp;#xfe0f;&amp;#x20e3;"/> <emoji name="five" unicode="&amp;#x0035;&amp;#xfe0f;&amp;#x20e3;"/> from "five"<linebreak/>
  <emoji name="flags" unicode="&amp;#x1f38f;"/> <emoji name="flags" unicode="&amp;#x1f38f;"/> from "flags"<linebreak/>
+ <emoji name="flamingo" unicode="&amp;#x1f9a9;"/> <emoji name="flamingo" unicode="&amp;#x1f9a9;"/> from "flamingo"<linebreak/>
  <emoji name="flashlight" unicode="&amp;#x1f526;"/> <emoji name="flashlight" unicode="&amp;#x1f526;"/> from "flashlight"<linebreak/>
+ <emoji name="flat_shoe" unicode="&amp;#x1f97f;"/> <emoji name="flat_shoe" unicode="&amp;#x1f97f;"/> from "flat_shoe"<linebreak/>
+ <emoji name="flatbread" unicode="&amp;#x1fad3;"/> <emoji name="flatbread" unicode="&amp;#x1fad3;"/> from "flatbread"<linebreak/>
  <emoji name="fleur_de_lis" unicode="&amp;#x269c;"/> <emoji name="fleur_de_lis" unicode="&amp;#x269c;"/> from "fleur_de_lis"<linebreak/>
  <emoji name="flight_arrival" unicode="&amp;#x1f6ec;"/> <emoji name="flight_arrival" unicode="&amp;#x1f6ec;"/> from "flight_arrival"<linebreak/>
  <emoji name="flight_departure" unicode="&amp;#x1f6eb;"/> <emoji name="flight_departure" unicode="&amp;#x1f6eb;"/> from "flight_departure"<linebreak/>
  <emoji name="floppy_disk" unicode="&amp;#x1f4be;"/> <emoji name="floppy_disk" unicode="&amp;#x1f4be;"/> from "floppy_disk"<linebreak/>
  <emoji name="flower_playing_cards" unicode="&amp;#x1f3b4;"/> <emoji name="flower_playing_cards" unicode="&amp;#x1f3b4;"/> from "flower_playing_cards"<linebreak/>
  <emoji name="flushed" unicode="&amp;#x1f633;"/> <emoji name="flushed" unicode="&amp;#x1f633;"/> from "flushed"<linebreak/>
+ <emoji name="fly" unicode="&amp;#x1fab0;"/> <emoji name="fly" unicode="&amp;#x1fab0;"/> from "fly"<linebreak/>
+ <emoji name="flying_disc" unicode="&amp;#x1f94f;"/> <emoji name="flying_disc" unicode="&amp;#x1f94f;"/> from "flying_disc"<linebreak/>
+ <emoji name="flying_saucer" unicode="&amp;#x1f6f8;"/> <emoji name="flying_saucer" unicode="&amp;#x1f6f8;"/> from "flying_saucer"<linebreak/>
  <emoji name="fog" unicode="&amp;#x1f32b;"/> <emoji name="fog" unicode="&amp;#x1f32b;"/> from "fog"<linebreak/>
  <emoji name="foggy" unicode="&amp;#x1f301;"/> <emoji name="foggy" unicode="&amp;#x1f301;"/> from "foggy"<linebreak/>
+ <emoji name="fondue" unicode="&amp;#x1fad5;"/> <emoji name="fondue" unicode="&amp;#x1fad5;"/> from "fondue"<linebreak/>
+ <emoji name="foot" unicode="&amp;#x1f9b6;"/> <emoji name="foot" unicode="&amp;#x1f9b6;"/> from "foot"<linebreak/>
  <emoji name="football" unicode="&amp;#x1f3c8;"/> <emoji name="football" unicode="&amp;#x1f3c8;"/> from "football"<linebreak/>
  <emoji name="footprints" unicode="&amp;#x1f463;"/> <emoji name="footprints" unicode="&amp;#x1f463;"/> from "footprints"<linebreak/>
  <emoji name="fork_and_knife" unicode="&amp;#x1f374;"/> <emoji name="fork_and_knife" unicode="&amp;#x1f374;"/> from "fork_and_knife"<linebreak/>
+ <emoji name="fortune_cookie" unicode="&amp;#x1f960;"/> <emoji name="fortune_cookie" unicode="&amp;#x1f960;"/> from "fortune_cookie"<linebreak/>
  <emoji name="fountain" unicode="&amp;#x26f2;"/> <emoji name="fountain" unicode="&amp;#x26f2;"/> from "fountain"<linebreak/>
  <emoji name="fountain_pen" unicode="&amp;#x1f58b;"/> <emoji name="fountain_pen" unicode="&amp;#x1f58b;"/> from "fountain_pen"<linebreak/>
- <emoji name="four" unicode="&amp;#x0034;&amp;#x20e3;"/> <emoji name="four" unicode="&amp;#x0034;&amp;#x20e3;"/> from "four"<linebreak/>
+ <emoji name="four" unicode="&amp;#x0034;&amp;#xfe0f;&amp;#x20e3;"/> <emoji name="four" unicode="&amp;#x0034;&amp;#xfe0f;&amp;#x20e3;"/> from "four"<linebreak/>
  <emoji name="four_leaf_clover" unicode="&amp;#x1f340;"/> <emoji name="four_leaf_clover" unicode="&amp;#x1f340;"/> from "four_leaf_clover"<linebreak/>
  <emoji name="fox_face" unicode="&amp;#x1f98a;"/> <emoji name="fox_face" unicode="&amp;#x1f98a;"/> from "fox_face"<linebreak/>
  <emoji name="fr" unicode="&amp;#x1f1eb;&amp;#x1f1f7;"/> <emoji name="fr" unicode="&amp;#x1f1eb;&amp;#x1f1f7;"/> from "fr"<linebreak/>
  <emoji name="frog" unicode="&amp;#x1f438;"/> <emoji name="frog" unicode="&amp;#x1f438;"/> from "frog"<linebreak/>
  <emoji name="frowning" unicode="&amp;#x1f626;"/> <emoji name="frowning" unicode="&amp;#x1f626;"/> from "frowning"<linebreak/>
  <emoji name="frowning_face" unicode="&amp;#x2639;"/> <emoji name="frowning_face" unicode="&amp;#x2639;"/> from "frowning_face"<linebreak/>
- <emoji name="frowning_man" unicode="&amp;#x1f64d;&amp;#x2642;"/> <emoji name="frowning_man" unicode="&amp;#x1f64d;&amp;#x2642;"/> from "frowning_man"<linebreak/>
- <emoji name="frowning_woman" unicode="&amp;#x1f64d;"/> <emoji name="frowning_woman" unicode="&amp;#x1f64d;"/> from "frowning_woman"<linebreak/>
+ <emoji name="frowning_man" unicode="&amp;#x1f64d;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="frowning_man" unicode="&amp;#x1f64d;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "frowning_man"<linebreak/>
+ <emoji name="frowning_person" unicode="&amp;#x1f64d;"/> <emoji name="frowning_person" unicode="&amp;#x1f64d;"/> from "frowning_person"<linebreak/>
+ <emoji name="frowning_woman" unicode="&amp;#x1f64d;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="frowning_woman" unicode="&amp;#x1f64d;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "frowning_woman"<linebreak/>
  <emoji name="fu" unicode="&amp;#x1f595;"/> <emoji name="fu" unicode="&amp;#x1f595;"/> from "fu"<linebreak/>
  <emoji name="fuelpump" unicode="&amp;#x26fd;"/> <emoji name="fuelpump" unicode="&amp;#x26fd;"/> from "fuelpump"<linebreak/>
  <emoji name="full_moon" unicode="&amp;#x1f315;"/> <emoji name="full_moon" unicode="&amp;#x1f315;"/> from "full_moon"<linebreak/>
  <emoji name="gabon" unicode="&amp;#x1f1ec;&amp;#x1f1e6;"/> <emoji name="gabon" unicode="&amp;#x1f1ec;&amp;#x1f1e6;"/> from "gabon"<linebreak/>
  <emoji name="gambia" unicode="&amp;#x1f1ec;&amp;#x1f1f2;"/> <emoji name="gambia" unicode="&amp;#x1f1ec;&amp;#x1f1f2;"/> from "gambia"<linebreak/>
  <emoji name="game_die" unicode="&amp;#x1f3b2;"/> <emoji name="game_die" unicode="&amp;#x1f3b2;"/> from "game_die"<linebreak/>
+ <emoji name="garlic" unicode="&amp;#x1f9c4;"/> <emoji name="garlic" unicode="&amp;#x1f9c4;"/> from "garlic"<linebreak/>
  <emoji name="gb" unicode="&amp;#x1f1ec;&amp;#x1f1e7;"/> <emoji name="gb" unicode="&amp;#x1f1ec;&amp;#x1f1e7;"/> from "gb"<linebreak/>
  <emoji name="gear" unicode="&amp;#x2699;"/> <emoji name="gear" unicode="&amp;#x2699;"/> from "gear"<linebreak/>
  <emoji name="gem" unicode="&amp;#x1f48e;"/> <emoji name="gem" unicode="&amp;#x1f48e;"/> from "gem"<linebreak/>
  <emoji name="gemini" unicode="&amp;#x264a;"/> <emoji name="gemini" unicode="&amp;#x264a;"/> from "gemini"<linebreak/>
+ <emoji name="genie" unicode="&amp;#x1f9de;"/> <emoji name="genie" unicode="&amp;#x1f9de;"/> from "genie"<linebreak/>
+ <emoji name="genie_man" unicode="&amp;#x1f9de;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="genie_man" unicode="&amp;#x1f9de;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "genie_man"<linebreak/>
+ <emoji name="genie_woman" unicode="&amp;#x1f9de;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="genie_woman" unicode="&amp;#x1f9de;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "genie_woman"<linebreak/>
  <emoji name="georgia" unicode="&amp;#x1f1ec;&amp;#x1f1ea;"/> <emoji name="georgia" unicode="&amp;#x1f1ec;&amp;#x1f1ea;"/> from "georgia"<linebreak/>
  <emoji name="ghana" unicode="&amp;#x1f1ec;&amp;#x1f1ed;"/> <emoji name="ghana" unicode="&amp;#x1f1ec;&amp;#x1f1ed;"/> from "ghana"<linebreak/>
  <emoji name="ghost" unicode="&amp;#x1f47b;"/> <emoji name="ghost" unicode="&amp;#x1f47b;"/> from "ghost"<linebreak/>
  <emoji name="gibraltar" unicode="&amp;#x1f1ec;&amp;#x1f1ee;"/> <emoji name="gibraltar" unicode="&amp;#x1f1ec;&amp;#x1f1ee;"/> from "gibraltar"<linebreak/>
  <emoji name="gift" unicode="&amp;#x1f381;"/> <emoji name="gift" unicode="&amp;#x1f381;"/> from "gift"<linebreak/>
  <emoji name="gift_heart" unicode="&amp;#x1f49d;"/> <emoji name="gift_heart" unicode="&amp;#x1f49d;"/> from "gift_heart"<linebreak/>
+ <emoji name="giraffe" unicode="&amp;#x1f992;"/> <emoji name="giraffe" unicode="&amp;#x1f992;"/> from "giraffe"<linebreak/>
  <emoji name="girl" unicode="&amp;#x1f467;"/> <emoji name="girl" unicode="&amp;#x1f467;"/> from "girl"<linebreak/>
  <emoji name="globe_with_meridians" unicode="&amp;#x1f310;"/> <emoji name="globe_with_meridians" unicode="&amp;#x1f310;"/> from "globe_with_meridians"<linebreak/>
+ <emoji name="gloves" unicode="&amp;#x1f9e4;"/> <emoji name="gloves" unicode="&amp;#x1f9e4;"/> from "gloves"<linebreak/>
  <emoji name="goal_net" unicode="&amp;#x1f945;"/> <emoji name="goal_net" unicode="&amp;#x1f945;"/> from "goal_net"<linebreak/>
  <emoji name="goat" unicode="&amp;#x1f410;"/> <emoji name="goat" unicode="&amp;#x1f410;"/> from "goat"<linebreak/>
+ <emoji name="goggles" unicode="&amp;#x1f97d;"/> <emoji name="goggles" unicode="&amp;#x1f97d;"/> from "goggles"<linebreak/>
  <emoji name="golf" unicode="&amp;#x26f3;"/> <emoji name="golf" unicode="&amp;#x26f3;"/> from "golf"<linebreak/>
- <emoji name="golfing_man" unicode="&amp;#x1f3cc;"/> <emoji name="golfing_man" unicode="&amp;#x1f3cc;"/> from "golfing_man"<linebreak/>
- <emoji name="golfing_woman" unicode="&amp;#x1f3cc;&amp;#x2640;"/> <emoji name="golfing_woman" unicode="&amp;#x1f3cc;&amp;#x2640;"/> from "golfing_woman"<linebreak/>
+ <emoji name="golfing" unicode="&amp;#x1f3cc;"/> <emoji name="golfing" unicode="&amp;#x1f3cc;"/> from "golfing"<linebreak/>
+ <emoji name="golfing_man" unicode="&amp;#x1f3cc;&amp;#xfe0f;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="golfing_man" unicode="&amp;#x1f3cc;&amp;#xfe0f;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "golfing_man"<linebreak/>
+ <emoji name="golfing_woman" unicode="&amp;#x1f3cc;&amp;#xfe0f;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="golfing_woman" unicode="&amp;#x1f3cc;&amp;#xfe0f;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "golfing_woman"<linebreak/>
  <emoji name="gorilla" unicode="&amp;#x1f98d;"/> <emoji name="gorilla" unicode="&amp;#x1f98d;"/> from "gorilla"<linebreak/>
  <emoji name="grapes" unicode="&amp;#x1f347;"/> <emoji name="grapes" unicode="&amp;#x1f347;"/> from "grapes"<linebreak/>
  <emoji name="greece" unicode="&amp;#x1f1ec;&amp;#x1f1f7;"/> <emoji name="greece" unicode="&amp;#x1f1ec;&amp;#x1f1f7;"/> from "greece"<linebreak/>
  <emoji name="green_apple" unicode="&amp;#x1f34f;"/> <emoji name="green_apple" unicode="&amp;#x1f34f;"/> from "green_apple"<linebreak/>
  <emoji name="green_book" unicode="&amp;#x1f4d7;"/> <emoji name="green_book" unicode="&amp;#x1f4d7;"/> from "green_book"<linebreak/>
+ <emoji name="green_circle" unicode="&amp;#x1f7e2;"/> <emoji name="green_circle" unicode="&amp;#x1f7e2;"/> from "green_circle"<linebreak/>
  <emoji name="green_heart" unicode="&amp;#x1f49a;"/> <emoji name="green_heart" unicode="&amp;#x1f49a;"/> from "green_heart"<linebreak/>
  <emoji name="green_salad" unicode="&amp;#x1f957;"/> <emoji name="green_salad" unicode="&amp;#x1f957;"/> from "green_salad"<linebreak/>
+ <emoji name="green_square" unicode="&amp;#x1f7e9;"/> <emoji name="green_square" unicode="&amp;#x1f7e9;"/> from "green_square"<linebreak/>
  <emoji name="greenland" unicode="&amp;#x1f1ec;&amp;#x1f1f1;"/> <emoji name="greenland" unicode="&amp;#x1f1ec;&amp;#x1f1f1;"/> from "greenland"<linebreak/>
  <emoji name="grenada" unicode="&amp;#x1f1ec;&amp;#x1f1e9;"/> <emoji name="grenada" unicode="&amp;#x1f1ec;&amp;#x1f1e9;"/> from "grenada"<linebreak/>
  <emoji name="grey_exclamation" unicode="&amp;#x2755;"/> <emoji name="grey_exclamation" unicode="&amp;#x2755;"/> from "grey_exclamation"<linebreak/>
  <emoji name="grinning" unicode="&amp;#x1f600;"/> <emoji name="grinning" unicode="&amp;#x1f600;"/> from "grinning"<linebreak/>
  <emoji name="guadeloupe" unicode="&amp;#x1f1ec;&amp;#x1f1f5;"/> <emoji name="guadeloupe" unicode="&amp;#x1f1ec;&amp;#x1f1f5;"/> from "guadeloupe"<linebreak/>
  <emoji name="guam" unicode="&amp;#x1f1ec;&amp;#x1f1fa;"/> <emoji name="guam" unicode="&amp;#x1f1ec;&amp;#x1f1fa;"/> from "guam"<linebreak/>
- <emoji name="guardsman" unicode="&amp;#x1f482;"/> <emoji name="guardsman" unicode="&amp;#x1f482;"/> from "guardsman"<linebreak/>
- <emoji name="guardswoman" unicode="&amp;#x1f482;&amp;#x2640;"/> <emoji name="guardswoman" unicode="&amp;#x1f482;&amp;#x2640;"/> from "guardswoman"<linebreak/>
+ <emoji name="guard" unicode="&amp;#x1f482;"/> <emoji name="guard" unicode="&amp;#x1f482;"/> from "guard"<linebreak/>
+ <emoji name="guardsman" unicode="&amp;#x1f482;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="guardsman" unicode="&amp;#x1f482;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "guardsman"<linebreak/>
+ <emoji name="guardswoman" unicode="&amp;#x1f482;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="guardswoman" unicode="&amp;#x1f482;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "guardswoman"<linebreak/>
  <emoji name="guatemala" unicode="&amp;#x1f1ec;&amp;#x1f1f9;"/> <emoji name="guatemala" unicode="&amp;#x1f1ec;&amp;#x1f1f9;"/> from "guatemala"<linebreak/>
  <emoji name="guernsey" unicode="&amp;#x1f1ec;&amp;#x1f1ec;"/> <emoji name="guernsey" unicode="&amp;#x1f1ec;&amp;#x1f1ec;"/> from "guernsey"<linebreak/>
+ <emoji name="guide_dog" unicode="&amp;#x1f9ae;"/> <emoji name="guide_dog" unicode="&amp;#x1f9ae;"/> from "guide_dog"<linebreak/>
  <emoji name="guinea" unicode="&amp;#x1f1ec;&amp;#x1f1f3;"/> <emoji name="guinea" unicode="&amp;#x1f1ec;&amp;#x1f1f3;"/> from "guinea"<linebreak/>
  <emoji name="guinea_bissau" unicode="&amp;#x1f1ec;&amp;#x1f1fc;"/> <emoji name="guinea_bissau" unicode="&amp;#x1f1ec;&amp;#x1f1fc;"/> from "guinea_bissau"<linebreak/>
  <emoji name="guitar" unicode="&amp;#x1f3b8;"/> <emoji name="guitar" unicode="&amp;#x1f3b8;"/> from "guitar"<linebreak/>
  <emoji name="gun" unicode="&amp;#x1f52b;"/> <emoji name="gun" unicode="&amp;#x1f52b;"/> from "gun"<linebreak/>
  <emoji name="guyana" unicode="&amp;#x1f1ec;&amp;#x1f1fe;"/> <emoji name="guyana" unicode="&amp;#x1f1ec;&amp;#x1f1fe;"/> from "guyana"<linebreak/>
  <emoji name="haircut" unicode="&amp;#x1f487;"/> <emoji name="haircut" unicode="&amp;#x1f487;"/> from "haircut"<linebreak/>
- <emoji name="haircut_man" unicode="&amp;#x1f487;&amp;#x2642;"/> <emoji name="haircut_man" unicode="&amp;#x1f487;&amp;#x2642;"/> from "haircut_man"<linebreak/>
- <emoji name="haircut_woman" unicode="&amp;#x1f487;"/> <emoji name="haircut_woman" unicode="&amp;#x1f487;"/> from "haircut_woman"<linebreak/>
+ <emoji name="haircut_man" unicode="&amp;#x1f487;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="haircut_man" unicode="&amp;#x1f487;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "haircut_man"<linebreak/>
+ <emoji name="haircut_woman" unicode="&amp;#x1f487;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="haircut_woman" unicode="&amp;#x1f487;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "haircut_woman"<linebreak/>
  <emoji name="haiti" unicode="&amp;#x1f1ed;&amp;#x1f1f9;"/> <emoji name="haiti" unicode="&amp;#x1f1ed;&amp;#x1f1f9;"/> from "haiti"<linebreak/>
  <emoji name="hamburger" unicode="&amp;#x1f354;"/> <emoji name="hamburger" unicode="&amp;#x1f354;"/> from "hamburger"<linebreak/>
  <emoji name="hammer" unicode="&amp;#x1f528;"/> <emoji name="hammer" unicode="&amp;#x1f528;"/> from "hammer"<linebreak/>
  <emoji name="hammer_and_wrench" unicode="&amp;#x1f6e0;"/> <emoji name="hammer_and_wrench" unicode="&amp;#x1f6e0;"/> from "hammer_and_wrench"<linebreak/>
  <emoji name="hamster" unicode="&amp;#x1f439;"/> <emoji name="hamster" unicode="&amp;#x1f439;"/> from "hamster"<linebreak/>
  <emoji name="hand" unicode="&amp;#x270b;"/> <emoji name="hand" unicode="&amp;#x270b;"/> from "hand"<linebreak/>
+ <emoji name="hand_over_mouth" unicode="&amp;#x1f92d;"/> <emoji name="hand_over_mouth" unicode="&amp;#x1f92d;"/> from "hand_over_mouth"<linebreak/>
  <emoji name="handbag" unicode="&amp;#x1f45c;"/> <emoji name="handbag" unicode="&amp;#x1f45c;"/> from "handbag"<linebreak/>
+ <emoji name="handball_person" unicode="&amp;#x1f93e;"/> <emoji name="handball_person" unicode="&amp;#x1f93e;"/> from "handball_person"<linebreak/>
  <emoji name="handshake" unicode="&amp;#x1f91d;"/> <emoji name="handshake" unicode="&amp;#x1f91d;"/> from "handshake"<linebreak/>
  <emoji name="hankey" unicode="&amp;#x1f4a9;"/> <emoji name="hankey" unicode="&amp;#x1f4a9;"/> from "hankey"<linebreak/>
- <emoji name="hash" unicode="&amp;#x0023;&amp;#x20e3;"/> <emoji name="hash" unicode="&amp;#x0023;&amp;#x20e3;"/> from "hash"<linebreak/>
+ <emoji name="hash" unicode="&amp;#x0023;&amp;#xfe0f;&amp;#x20e3;"/> <emoji name="hash" unicode="&amp;#x0023;&amp;#xfe0f;&amp;#x20e3;"/> from "hash"<linebreak/>
  <emoji name="hatched_chick" unicode="&amp;#x1f425;"/> <emoji name="hatched_chick" unicode="&amp;#x1f425;"/> from "hatched_chick"<linebreak/>
  <emoji name="hatching_chick" unicode="&amp;#x1f423;"/> <emoji name="hatching_chick" unicode="&amp;#x1f423;"/> from "hatching_chick"<linebreak/>
  <emoji name="headphones" unicode="&amp;#x1f3a7;"/> <emoji name="headphones" unicode="&amp;#x1f3a7;"/> from "headphones"<linebreak/>
+ <emoji name="headstone" unicode="&amp;#x1faa6;"/> <emoji name="headstone" unicode="&amp;#x1faa6;"/> from "headstone"<linebreak/>
+ <emoji name="health_worker" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x2695;&amp;#xfe0f;"/> <emoji name="health_worker" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x2695;&amp;#xfe0f;"/> from "health_worker"<linebreak/>
  <emoji name="hear_no_evil" unicode="&amp;#x1f649;"/> <emoji name="hear_no_evil" unicode="&amp;#x1f649;"/> from "hear_no_evil"<linebreak/>
- <emoji name="heart" unicode="&amp;#x2764;"/> <emoji name="heart" unicode="&amp;#x2764;"/> from "heart"<linebreak/>
+ <emoji name="heard_mcdonald_islands" unicode="&amp;#x1f1ed;&amp;#x1f1f2;"/> <emoji name="heard_mcdonald_islands" unicode="&amp;#x1f1ed;&amp;#x1f1f2;"/> from "heard_mcdonald_islands"<linebreak/>
+ <emoji name="heart" unicode="&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f525;"/> <emoji name="heart" unicode="&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f525;"/> from "heart"<linebreak/>
  <emoji name="heart_decoration" unicode="&amp;#x1f49f;"/> <emoji name="heart_decoration" unicode="&amp;#x1f49f;"/> from "heart_decoration"<linebreak/>
  <emoji name="heart_eyes" unicode="&amp;#x1f60d;"/> <emoji name="heart_eyes" unicode="&amp;#x1f60d;"/> from "heart_eyes"<linebreak/>
  <emoji name="heart_eyes_cat" unicode="&amp;#x1f63b;"/> <emoji name="heart_eyes_cat" unicode="&amp;#x1f63b;"/> from "heart_eyes_cat"<linebreak/>
+ <emoji name="heart_on_fire" unicode="&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f525;"/> <emoji name="heart_on_fire" unicode="&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1f525;"/> from "heart_on_fire"<linebreak/>
  <emoji name="heartbeat" unicode="&amp;#x1f493;"/> <emoji name="heartbeat" unicode="&amp;#x1f493;"/> from "heartbeat"<linebreak/>
  <emoji name="heartpulse" unicode="&amp;#x1f497;"/> <emoji name="heartpulse" unicode="&amp;#x1f497;"/> from "heartpulse"<linebreak/>
  <emoji name="hearts" unicode="&amp;#x2665;"/> <emoji name="hearts" unicode="&amp;#x2665;"/> from "hearts"<linebreak/>
  <emoji name="heavy_minus_sign" unicode="&amp;#x2796;"/> <emoji name="heavy_minus_sign" unicode="&amp;#x2796;"/> from "heavy_minus_sign"<linebreak/>
  <emoji name="heavy_multiplication_x" unicode="&amp;#x2716;"/> <emoji name="heavy_multiplication_x" unicode="&amp;#x2716;"/> from "heavy_multiplication_x"<linebreak/>
  <emoji name="heavy_plus_sign" unicode="&amp;#x2795;"/> <emoji name="heavy_plus_sign" unicode="&amp;#x2795;"/> from "heavy_plus_sign"<linebreak/>
+ <emoji name="hedgehog" unicode="&amp;#x1f994;"/> <emoji name="hedgehog" unicode="&amp;#x1f994;"/> from "hedgehog"<linebreak/>
  <emoji name="helicopter" unicode="&amp;#x1f681;"/> <emoji name="helicopter" unicode="&amp;#x1f681;"/> from "helicopter"<linebreak/>
  <emoji name="herb" unicode="&amp;#x1f33f;"/> <emoji name="herb" unicode="&amp;#x1f33f;"/> from "herb"<linebreak/>
  <emoji name="hibiscus" unicode="&amp;#x1f33a;"/> <emoji name="hibiscus" unicode="&amp;#x1f33a;"/> from "hibiscus"<linebreak/>
  <emoji name="high_brightness" unicode="&amp;#x1f506;"/> <emoji name="high_brightness" unicode="&amp;#x1f506;"/> from "high_brightness"<linebreak/>
  <emoji name="high_heel" unicode="&amp;#x1f460;"/> <emoji name="high_heel" unicode="&amp;#x1f460;"/> from "high_heel"<linebreak/>
+ <emoji name="hiking_boot" unicode="&amp;#x1f97e;"/> <emoji name="hiking_boot" unicode="&amp;#x1f97e;"/> from "hiking_boot"<linebreak/>
+ <emoji name="hindu_temple" unicode="&amp;#x1f6d5;"/> <emoji name="hindu_temple" unicode="&amp;#x1f6d5;"/> from "hindu_temple"<linebreak/>
+ <emoji name="hippopotamus" unicode="&amp;#x1f99b;"/> <emoji name="hippopotamus" unicode="&amp;#x1f99b;"/> from "hippopotamus"<linebreak/>
  <emoji name="hocho" unicode="&amp;#x1f52a;"/> <emoji name="hocho" unicode="&amp;#x1f52a;"/> from "hocho"<linebreak/>
  <emoji name="hole" unicode="&amp;#x1f573;"/> <emoji name="hole" unicode="&amp;#x1f573;"/> from "hole"<linebreak/>
  <emoji name="honduras" unicode="&amp;#x1f1ed;&amp;#x1f1f3;"/> <emoji name="honduras" unicode="&amp;#x1f1ed;&amp;#x1f1f3;"/> from "honduras"<linebreak/>
  <emoji name="honey_pot" unicode="&amp;#x1f36f;"/> <emoji name="honey_pot" unicode="&amp;#x1f36f;"/> from "honey_pot"<linebreak/>
  <emoji name="honeybee" unicode="&amp;#x1f41d;"/> <emoji name="honeybee" unicode="&amp;#x1f41d;"/> from "honeybee"<linebreak/>
  <emoji name="hong_kong" unicode="&amp;#x1f1ed;&amp;#x1f1f0;"/> <emoji name="hong_kong" unicode="&amp;#x1f1ed;&amp;#x1f1f0;"/> from "hong_kong"<linebreak/>
+ <emoji name="hook" unicode="&amp;#x1fa9d;"/> <emoji name="hook" unicode="&amp;#x1fa9d;"/> from "hook"<linebreak/>
  <emoji name="horse" unicode="&amp;#x1f434;"/> <emoji name="horse" unicode="&amp;#x1f434;"/> from "horse"<linebreak/>
  <emoji name="horse_racing" unicode="&amp;#x1f3c7;"/> <emoji name="horse_racing" unicode="&amp;#x1f3c7;"/> from "horse_racing"<linebreak/>
  <emoji name="hospital" unicode="&amp;#x1f3e5;"/> <emoji name="hospital" unicode="&amp;#x1f3e5;"/> from "hospital"<linebreak/>
+ <emoji name="hot_face" unicode="&amp;#x1f975;"/> <emoji name="hot_face" unicode="&amp;#x1f975;"/> from "hot_face"<linebreak/>
  <emoji name="hot_pepper" unicode="&amp;#x1f336;"/> <emoji name="hot_pepper" unicode="&amp;#x1f336;"/> from "hot_pepper"<linebreak/>
  <emoji name="hotdog" unicode="&amp;#x1f32d;"/> <emoji name="hotdog" unicode="&amp;#x1f32d;"/> from "hotdog"<linebreak/>
  <emoji name="hotel" unicode="&amp;#x1f3e8;"/> <emoji name="hotel" unicode="&amp;#x1f3e8;"/> from "hotel"<linebreak/>
  <emoji name="hugs" unicode="&amp;#x1f917;"/> <emoji name="hugs" unicode="&amp;#x1f917;"/> from "hugs"<linebreak/>
  <emoji name="hungary" unicode="&amp;#x1f1ed;&amp;#x1f1fa;"/> <emoji name="hungary" unicode="&amp;#x1f1ed;&amp;#x1f1fa;"/> from "hungary"<linebreak/>
  <emoji name="hushed" unicode="&amp;#x1f62f;"/> <emoji name="hushed" unicode="&amp;#x1f62f;"/> from "hushed"<linebreak/>
+ <emoji name="hut" unicode="&amp;#x1f6d6;"/> <emoji name="hut" unicode="&amp;#x1f6d6;"/> from "hut"<linebreak/>
  <emoji name="ice_cream" unicode="&amp;#x1f368;"/> <emoji name="ice_cream" unicode="&amp;#x1f368;"/> from "ice_cream"<linebreak/>
+ <emoji name="ice_cube" unicode="&amp;#x1f9ca;"/> <emoji name="ice_cube" unicode="&amp;#x1f9ca;"/> from "ice_cube"<linebreak/>
  <emoji name="ice_hockey" unicode="&amp;#x1f3d2;"/> <emoji name="ice_hockey" unicode="&amp;#x1f3d2;"/> from "ice_hockey"<linebreak/>
  <emoji name="ice_skate" unicode="&amp;#x26f8;"/> <emoji name="ice_skate" unicode="&amp;#x26f8;"/> from "ice_skate"<linebreak/>
  <emoji name="icecream" unicode="&amp;#x1f366;"/> <emoji name="icecream" unicode="&amp;#x1f366;"/> from "icecream"<linebreak/>
  <emoji name="incoming_envelope" unicode="&amp;#x1f4e8;"/> <emoji name="incoming_envelope" unicode="&amp;#x1f4e8;"/> from "incoming_envelope"<linebreak/>
  <emoji name="india" unicode="&amp;#x1f1ee;&amp;#x1f1f3;"/> <emoji name="india" unicode="&amp;#x1f1ee;&amp;#x1f1f3;"/> from "india"<linebreak/>
  <emoji name="indonesia" unicode="&amp;#x1f1ee;&amp;#x1f1e9;"/> <emoji name="indonesia" unicode="&amp;#x1f1ee;&amp;#x1f1e9;"/> from "indonesia"<linebreak/>
+ <emoji name="infinity" unicode="&amp;#x267e;"/> <emoji name="infinity" unicode="&amp;#x267e;"/> from "infinity"<linebreak/>
  <emoji name="information_desk_person" unicode="&amp;#x1f481;"/> <emoji name="information_desk_person" unicode="&amp;#x1f481;"/> from "information_desk_person"<linebreak/>
  <emoji name="information_source" unicode="&amp;#x2139;"/> <emoji name="information_source" unicode="&amp;#x2139;"/> from "information_source"<linebreak/>
  <emoji name="innocent" unicode="&amp;#x1f607;"/> <emoji name="innocent" unicode="&amp;#x1f607;"/> from "innocent"<linebreak/>
  <emoji name="japanese_ogre" unicode="&amp;#x1f479;"/> <emoji name="japanese_ogre" unicode="&amp;#x1f479;"/> from "japanese_ogre"<linebreak/>
  <emoji name="jeans" unicode="&amp;#x1f456;"/> <emoji name="jeans" unicode="&amp;#x1f456;"/> from "jeans"<linebreak/>
  <emoji name="jersey" unicode="&amp;#x1f1ef;&amp;#x1f1ea;"/> <emoji name="jersey" unicode="&amp;#x1f1ef;&amp;#x1f1ea;"/> from "jersey"<linebreak/>
+ <emoji name="jigsaw" unicode="&amp;#x1f9e9;"/> <emoji name="jigsaw" unicode="&amp;#x1f9e9;"/> from "jigsaw"<linebreak/>
  <emoji name="jordan" unicode="&amp;#x1f1ef;&amp;#x1f1f4;"/> <emoji name="jordan" unicode="&amp;#x1f1ef;&amp;#x1f1f4;"/> from "jordan"<linebreak/>
  <emoji name="joy" unicode="&amp;#x1f602;"/> <emoji name="joy" unicode="&amp;#x1f602;"/> from "joy"<linebreak/>
  <emoji name="joy_cat" unicode="&amp;#x1f639;"/> <emoji name="joy_cat" unicode="&amp;#x1f639;"/> from "joy_cat"<linebreak/>
  <emoji name="joystick" unicode="&amp;#x1f579;"/> <emoji name="joystick" unicode="&amp;#x1f579;"/> from "joystick"<linebreak/>
  <emoji name="jp" unicode="&amp;#x1f1ef;&amp;#x1f1f5;"/> <emoji name="jp" unicode="&amp;#x1f1ef;&amp;#x1f1f5;"/> from "jp"<linebreak/>
+ <emoji name="judge" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x2696;&amp;#xfe0f;"/> <emoji name="judge" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x2696;&amp;#xfe0f;"/> from "judge"<linebreak/>
+ <emoji name="juggling_person" unicode="&amp;#x1f939;"/> <emoji name="juggling_person" unicode="&amp;#x1f939;"/> from "juggling_person"<linebreak/>
  <emoji name="kaaba" unicode="&amp;#x1f54b;"/> <emoji name="kaaba" unicode="&amp;#x1f54b;"/> from "kaaba"<linebreak/>
+ <emoji name="kangaroo" unicode="&amp;#x1f998;"/> <emoji name="kangaroo" unicode="&amp;#x1f998;"/> from "kangaroo"<linebreak/>
  <emoji name="kazakhstan" unicode="&amp;#x1f1f0;&amp;#x1f1ff;"/> <emoji name="kazakhstan" unicode="&amp;#x1f1f0;&amp;#x1f1ff;"/> from "kazakhstan"<linebreak/>
  <emoji name="kenya" unicode="&amp;#x1f1f0;&amp;#x1f1ea;"/> <emoji name="kenya" unicode="&amp;#x1f1f0;&amp;#x1f1ea;"/> from "kenya"<linebreak/>
  <emoji name="key" unicode="&amp;#x1f511;"/> <emoji name="key" unicode="&amp;#x1f511;"/> from "key"<linebreak/>
  <emoji name="kissing_closed_eyes" unicode="&amp;#x1f61a;"/> <emoji name="kissing_closed_eyes" unicode="&amp;#x1f61a;"/> from "kissing_closed_eyes"<linebreak/>
  <emoji name="kissing_heart" unicode="&amp;#x1f618;"/> <emoji name="kissing_heart" unicode="&amp;#x1f618;"/> from "kissing_heart"<linebreak/>
  <emoji name="kissing_smiling_eyes" unicode="&amp;#x1f619;"/> <emoji name="kissing_smiling_eyes" unicode="&amp;#x1f619;"/> from "kissing_smiling_eyes"<linebreak/>
+ <emoji name="kite" unicode="&amp;#x1fa81;"/> <emoji name="kite" unicode="&amp;#x1fa81;"/> from "kite"<linebreak/>
  <emoji name="kiwi_fruit" unicode="&amp;#x1f95d;"/> <emoji name="kiwi_fruit" unicode="&amp;#x1f95d;"/> from "kiwi_fruit"<linebreak/>
+ <emoji name="kneeling_man" unicode="&amp;#x1f9ce;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="kneeling_man" unicode="&amp;#x1f9ce;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "kneeling_man"<linebreak/>
+ <emoji name="kneeling_person" unicode="&amp;#x1f9ce;"/> <emoji name="kneeling_person" unicode="&amp;#x1f9ce;"/> from "kneeling_person"<linebreak/>
+ <emoji name="kneeling_woman" unicode="&amp;#x1f9ce;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="kneeling_woman" unicode="&amp;#x1f9ce;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "kneeling_woman"<linebreak/>
  <emoji name="knife" unicode="&amp;#x1f52a;"/> <emoji name="knife" unicode="&amp;#x1f52a;"/> from "knife"<linebreak/>
+ <emoji name="knot" unicode="&amp;#x1faa2;"/> <emoji name="knot" unicode="&amp;#x1faa2;"/> from "knot"<linebreak/>
  <emoji name="koala" unicode="&amp;#x1f428;"/> <emoji name="koala" unicode="&amp;#x1f428;"/> from "koala"<linebreak/>
  <emoji name="koko" unicode="&amp;#x1f201;"/> <emoji name="koko" unicode="&amp;#x1f201;"/> from "koko"<linebreak/>
  <emoji name="kosovo" unicode="&amp;#x1f1fd;&amp;#x1f1f0;"/> <emoji name="kosovo" unicode="&amp;#x1f1fd;&amp;#x1f1f0;"/> from "kosovo"<linebreak/>
  <emoji name="kr" unicode="&amp;#x1f1f0;&amp;#x1f1f7;"/> <emoji name="kr" unicode="&amp;#x1f1f0;&amp;#x1f1f7;"/> from "kr"<linebreak/>
  <emoji name="kuwait" unicode="&amp;#x1f1f0;&amp;#x1f1fc;"/> <emoji name="kuwait" unicode="&amp;#x1f1f0;&amp;#x1f1fc;"/> from "kuwait"<linebreak/>
  <emoji name="kyrgyzstan" unicode="&amp;#x1f1f0;&amp;#x1f1ec;"/> <emoji name="kyrgyzstan" unicode="&amp;#x1f1f0;&amp;#x1f1ec;"/> from "kyrgyzstan"<linebreak/>
+ <emoji name="lab_coat" unicode="&amp;#x1f97c;"/> <emoji name="lab_coat" unicode="&amp;#x1f97c;"/> from "lab_coat"<linebreak/>
  <emoji name="label" unicode="&amp;#x1f3f7;"/> <emoji name="label" unicode="&amp;#x1f3f7;"/> from "label"<linebreak/>
+ <emoji name="lacrosse" unicode="&amp;#x1f94d;"/> <emoji name="lacrosse" unicode="&amp;#x1f94d;"/> from "lacrosse"<linebreak/>
+ <emoji name="ladder" unicode="&amp;#x1fa9c;"/> <emoji name="ladder" unicode="&amp;#x1fa9c;"/> from "ladder"<linebreak/>
+ <emoji name="lady_beetle" unicode="&amp;#x1f41e;"/> <emoji name="lady_beetle" unicode="&amp;#x1f41e;"/> from "lady_beetle"<linebreak/>
  <emoji name="lantern" unicode="&amp;#x1f3ee;"/> <emoji name="lantern" unicode="&amp;#x1f3ee;"/> from "lantern"<linebreak/>
  <emoji name="laos" unicode="&amp;#x1f1f1;&amp;#x1f1e6;"/> <emoji name="laos" unicode="&amp;#x1f1f1;&amp;#x1f1e6;"/> from "laos"<linebreak/>
  <emoji name="large_blue_circle" unicode="&amp;#x1f535;"/> <emoji name="large_blue_circle" unicode="&amp;#x1f535;"/> from "large_blue_circle"<linebreak/>
  <emoji name="latin_cross" unicode="&amp;#x271d;"/> <emoji name="latin_cross" unicode="&amp;#x271d;"/> from "latin_cross"<linebreak/>
  <emoji name="latvia" unicode="&amp;#x1f1f1;&amp;#x1f1fb;"/> <emoji name="latvia" unicode="&amp;#x1f1f1;&amp;#x1f1fb;"/> from "latvia"<linebreak/>
  <emoji name="laughing" unicode="&amp;#x1f606;"/> <emoji name="laughing" unicode="&amp;#x1f606;"/> from "laughing"<linebreak/>
+ <emoji name="leafy_green" unicode="&amp;#x1f96c;"/> <emoji name="leafy_green" unicode="&amp;#x1f96c;"/> from "leafy_green"<linebreak/>
  <emoji name="leaves" unicode="&amp;#x1f343;"/> <emoji name="leaves" unicode="&amp;#x1f343;"/> from "leaves"<linebreak/>
  <emoji name="lebanon" unicode="&amp;#x1f1f1;&amp;#x1f1e7;"/> <emoji name="lebanon" unicode="&amp;#x1f1f1;&amp;#x1f1e7;"/> from "lebanon"<linebreak/>
  <emoji name="ledger" unicode="&amp;#x1f4d2;"/> <emoji name="ledger" unicode="&amp;#x1f4d2;"/> from "ledger"<linebreak/>
  <emoji name="left_luggage" unicode="&amp;#x1f6c5;"/> <emoji name="left_luggage" unicode="&amp;#x1f6c5;"/> from "left_luggage"<linebreak/>
  <emoji name="left_right_arrow" unicode="&amp;#x2194;"/> <emoji name="left_right_arrow" unicode="&amp;#x2194;"/> from "left_right_arrow"<linebreak/>
+ <emoji name="left_speech_bubble" unicode="&amp;#x1f5e8;"/> <emoji name="left_speech_bubble" unicode="&amp;#x1f5e8;"/> from "left_speech_bubble"<linebreak/>
  <emoji name="leftwards_arrow_with_hook" unicode="&amp;#x21a9;"/> <emoji name="leftwards_arrow_with_hook" unicode="&amp;#x21a9;"/> from "leftwards_arrow_with_hook"<linebreak/>
+ <emoji name="leg" unicode="&amp;#x1f9b5;"/> <emoji name="leg" unicode="&amp;#x1f9b5;"/> from "leg"<linebreak/>
  <emoji name="lemon" unicode="&amp;#x1f34b;"/> <emoji name="lemon" unicode="&amp;#x1f34b;"/> from "lemon"<linebreak/>
  <emoji name="leo" unicode="&amp;#x264c;"/> <emoji name="leo" unicode="&amp;#x264c;"/> from "leo"<linebreak/>
  <emoji name="leopard" unicode="&amp;#x1f406;"/> <emoji name="leopard" unicode="&amp;#x1f406;"/> from "leopard"<linebreak/>
  <emoji name="lipstick" unicode="&amp;#x1f484;"/> <emoji name="lipstick" unicode="&amp;#x1f484;"/> from "lipstick"<linebreak/>
  <emoji name="lithuania" unicode="&amp;#x1f1f1;&amp;#x1f1f9;"/> <emoji name="lithuania" unicode="&amp;#x1f1f1;&amp;#x1f1f9;"/> from "lithuania"<linebreak/>
  <emoji name="lizard" unicode="&amp;#x1f98e;"/> <emoji name="lizard" unicode="&amp;#x1f98e;"/> from "lizard"<linebreak/>
+ <emoji name="llama" unicode="&amp;#x1f999;"/> <emoji name="llama" unicode="&amp;#x1f999;"/> from "llama"<linebreak/>
+ <emoji name="lobster" unicode="&amp;#x1f99e;"/> <emoji name="lobster" unicode="&amp;#x1f99e;"/> from "lobster"<linebreak/>
  <emoji name="lock" unicode="&amp;#x1f512;"/> <emoji name="lock" unicode="&amp;#x1f512;"/> from "lock"<linebreak/>
  <emoji name="lock_with_ink_pen" unicode="&amp;#x1f50f;"/> <emoji name="lock_with_ink_pen" unicode="&amp;#x1f50f;"/> from "lock_with_ink_pen"<linebreak/>
  <emoji name="lollipop" unicode="&amp;#x1f36d;"/> <emoji name="lollipop" unicode="&amp;#x1f36d;"/> from "lollipop"<linebreak/>
+ <emoji name="long_drum" unicode="&amp;#x1fa98;"/> <emoji name="long_drum" unicode="&amp;#x1fa98;"/> from "long_drum"<linebreak/>
  <emoji name="loop" unicode="&amp;#x27bf;"/> <emoji name="loop" unicode="&amp;#x27bf;"/> from "loop"<linebreak/>
+ <emoji name="lotion_bottle" unicode="&amp;#x1f9f4;"/> <emoji name="lotion_bottle" unicode="&amp;#x1f9f4;"/> from "lotion_bottle"<linebreak/>
+ <emoji name="lotus_position" unicode="&amp;#x1f9d8;"/> <emoji name="lotus_position" unicode="&amp;#x1f9d8;"/> from "lotus_position"<linebreak/>
+ <emoji name="lotus_position_man" unicode="&amp;#x1f9d8;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="lotus_position_man" unicode="&amp;#x1f9d8;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "lotus_position_man"<linebreak/>
+ <emoji name="lotus_position_woman" unicode="&amp;#x1f9d8;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="lotus_position_woman" unicode="&amp;#x1f9d8;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "lotus_position_woman"<linebreak/>
  <emoji name="loud_sound" unicode="&amp;#x1f50a;"/> <emoji name="loud_sound" unicode="&amp;#x1f50a;"/> from "loud_sound"<linebreak/>
  <emoji name="loudspeaker" unicode="&amp;#x1f4e2;"/> <emoji name="loudspeaker" unicode="&amp;#x1f4e2;"/> from "loudspeaker"<linebreak/>
  <emoji name="love_hotel" unicode="&amp;#x1f3e9;"/> <emoji name="love_hotel" unicode="&amp;#x1f3e9;"/> from "love_hotel"<linebreak/>
  <emoji name="love_letter" unicode="&amp;#x1f48c;"/> <emoji name="love_letter" unicode="&amp;#x1f48c;"/> from "love_letter"<linebreak/>
+ <emoji name="love_you_gesture" unicode="&amp;#x1f91f;"/> <emoji name="love_you_gesture" unicode="&amp;#x1f91f;"/> from "love_you_gesture"<linebreak/>
  <emoji name="low_brightness" unicode="&amp;#x1f505;"/> <emoji name="low_brightness" unicode="&amp;#x1f505;"/> from "low_brightness"<linebreak/>
+ <emoji name="luggage" unicode="&amp;#x1f9f3;"/> <emoji name="luggage" unicode="&amp;#x1f9f3;"/> from "luggage"<linebreak/>
+ <emoji name="lungs" unicode="&amp;#x1fac1;"/> <emoji name="lungs" unicode="&amp;#x1fac1;"/> from "lungs"<linebreak/>
  <emoji name="luxembourg" unicode="&amp;#x1f1f1;&amp;#x1f1fa;"/> <emoji name="luxembourg" unicode="&amp;#x1f1f1;&amp;#x1f1fa;"/> from "luxembourg"<linebreak/>
  <emoji name="lying_face" unicode="&amp;#x1f925;"/> <emoji name="lying_face" unicode="&amp;#x1f925;"/> from "lying_face"<linebreak/>
  <emoji name="m" unicode="&amp;#x24c2;"/> <emoji name="m" unicode="&amp;#x24c2;"/> from "m"<linebreak/>
  <emoji name="madagascar" unicode="&amp;#x1f1f2;&amp;#x1f1ec;"/> <emoji name="madagascar" unicode="&amp;#x1f1f2;&amp;#x1f1ec;"/> from "madagascar"<linebreak/>
  <emoji name="mag" unicode="&amp;#x1f50d;"/> <emoji name="mag" unicode="&amp;#x1f50d;"/> from "mag"<linebreak/>
  <emoji name="mag_right" unicode="&amp;#x1f50e;"/> <emoji name="mag_right" unicode="&amp;#x1f50e;"/> from "mag_right"<linebreak/>
+ <emoji name="mage" unicode="&amp;#x1f9d9;"/> <emoji name="mage" unicode="&amp;#x1f9d9;"/> from "mage"<linebreak/>
+ <emoji name="mage_man" unicode="&amp;#x1f9d9;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="mage_man" unicode="&amp;#x1f9d9;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "mage_man"<linebreak/>
+ <emoji name="mage_woman" unicode="&amp;#x1f9d9;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="mage_woman" unicode="&amp;#x1f9d9;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "mage_woman"<linebreak/>
+ <emoji name="magic_wand" unicode="&amp;#x1fa84;"/> <emoji name="magic_wand" unicode="&amp;#x1fa84;"/> from "magic_wand"<linebreak/>
+ <emoji name="magnet" unicode="&amp;#x1f9f2;"/> <emoji name="magnet" unicode="&amp;#x1f9f2;"/> from "magnet"<linebreak/>
  <emoji name="mahjong" unicode="&amp;#x1f004;"/> <emoji name="mahjong" unicode="&amp;#x1f004;"/> from "mahjong"<linebreak/>
  <emoji name="mailbox" unicode="&amp;#x1f4eb;"/> <emoji name="mailbox" unicode="&amp;#x1f4eb;"/> from "mailbox"<linebreak/>
  <emoji name="mailbox_closed" unicode="&amp;#x1f4ea;"/> <emoji name="mailbox_closed" unicode="&amp;#x1f4ea;"/> from "mailbox_closed"<linebreak/>
  <emoji name="malawi" unicode="&amp;#x1f1f2;&amp;#x1f1fc;"/> <emoji name="malawi" unicode="&amp;#x1f1f2;&amp;#x1f1fc;"/> from "malawi"<linebreak/>
  <emoji name="malaysia" unicode="&amp;#x1f1f2;&amp;#x1f1fe;"/> <emoji name="malaysia" unicode="&amp;#x1f1f2;&amp;#x1f1fe;"/> from "malaysia"<linebreak/>
  <emoji name="maldives" unicode="&amp;#x1f1f2;&amp;#x1f1fb;"/> <emoji name="maldives" unicode="&amp;#x1f1f2;&amp;#x1f1fb;"/> from "maldives"<linebreak/>
- <emoji name="male_detective" unicode="&amp;#x1f575;"/> <emoji name="male_detective" unicode="&amp;#x1f575;"/> from "male_detective"<linebreak/>
+ <emoji name="male_detective" unicode="&amp;#x1f575;&amp;#xfe0f;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="male_detective" unicode="&amp;#x1f575;&amp;#xfe0f;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "male_detective"<linebreak/>
+ <emoji name="male_sign" unicode="&amp;#x2642;"/> <emoji name="male_sign" unicode="&amp;#x2642;"/> from "male_sign"<linebreak/>
  <emoji name="mali" unicode="&amp;#x1f1f2;&amp;#x1f1f1;"/> <emoji name="mali" unicode="&amp;#x1f1f2;&amp;#x1f1f1;"/> from "mali"<linebreak/>
  <emoji name="malta" unicode="&amp;#x1f1f2;&amp;#x1f1f9;"/> <emoji name="malta" unicode="&amp;#x1f1f2;&amp;#x1f1f9;"/> from "malta"<linebreak/>
+ <emoji name="mammoth" unicode="&amp;#x1f9a3;"/> <emoji name="mammoth" unicode="&amp;#x1f9a3;"/> from "mammoth"<linebreak/>
  <emoji name="man" unicode="&amp;#x1f468;"/> <emoji name="man" unicode="&amp;#x1f468;"/> from "man"<linebreak/>
- <emoji name="man_artist" unicode="&amp;#x1f468;&amp;#x1f3a8;"/> <emoji name="man_artist" unicode="&amp;#x1f468;&amp;#x1f3a8;"/> from "man_artist"<linebreak/>
- <emoji name="man_astronaut" unicode="&amp;#x1f468;&amp;#x1f680;"/> <emoji name="man_astronaut" unicode="&amp;#x1f468;&amp;#x1f680;"/> from "man_astronaut"<linebreak/>
- <emoji name="man_cartwheeling" unicode="&amp;#x1f938;&amp;#x2642;"/> <emoji name="man_cartwheeling" unicode="&amp;#x1f938;&amp;#x2642;"/> from "man_cartwheeling"<linebreak/>
- <emoji name="man_cook" unicode="&amp;#x1f468;&amp;#x1f373;"/> <emoji name="man_cook" unicode="&amp;#x1f468;&amp;#x1f373;"/> from "man_cook"<linebreak/>
+ <emoji name="man_artist" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f3a8;"/> <emoji name="man_artist" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f3a8;"/> from "man_artist"<linebreak/>
+ <emoji name="man_astronaut" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f680;"/> <emoji name="man_astronaut" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f680;"/> from "man_astronaut"<linebreak/>
+ <emoji name="man_beard" unicode="&amp;#x1f9d4;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="man_beard" unicode="&amp;#x1f9d4;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "man_beard"<linebreak/>
+ <emoji name="man_cartwheeling" unicode="&amp;#x1f938;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="man_cartwheeling" unicode="&amp;#x1f938;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "man_cartwheeling"<linebreak/>
+ <emoji name="man_cook" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f373;"/> <emoji name="man_cook" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f373;"/> from "man_cook"<linebreak/>
  <emoji name="man_dancing" unicode="&amp;#x1f57a;"/> <emoji name="man_dancing" unicode="&amp;#x1f57a;"/> from "man_dancing"<linebreak/>
- <emoji name="man_facepalming" unicode="&amp;#x1f926;&amp;#x2642;"/> <emoji name="man_facepalming" unicode="&amp;#x1f926;&amp;#x2642;"/> from "man_facepalming"<linebreak/>
- <emoji name="man_factory_worker" unicode="&amp;#x1f468;&amp;#x1f3ed;"/> <emoji name="man_factory_worker" unicode="&amp;#x1f468;&amp;#x1f3ed;"/> from "man_factory_worker"<linebreak/>
- <emoji name="man_farmer" unicode="&amp;#x1f468;&amp;#x1f33e;"/> <emoji name="man_farmer" unicode="&amp;#x1f468;&amp;#x1f33e;"/> from "man_farmer"<linebreak/>
- <emoji name="man_firefighter" unicode="&amp;#x1f468;&amp;#x1f692;"/> <emoji name="man_firefighter" unicode="&amp;#x1f468;&amp;#x1f692;"/> from "man_firefighter"<linebreak/>
- <emoji name="man_health_worker" unicode="&amp;#x1f468;&amp;#x2695;"/> <emoji name="man_health_worker" unicode="&amp;#x1f468;&amp;#x2695;"/> from "man_health_worker"<linebreak/>
- <emoji name="man_in_tuxedo" unicode="&amp;#x1f935;"/> <emoji name="man_in_tuxedo" unicode="&amp;#x1f935;"/> from "man_in_tuxedo"<linebreak/>
- <emoji name="man_judge" unicode="&amp;#x1f468;&amp;#x2696;"/> <emoji name="man_judge" unicode="&amp;#x1f468;&amp;#x2696;"/> from "man_judge"<linebreak/>
- <emoji name="man_juggling" unicode="&amp;#x1f939;&amp;#x2642;"/> <emoji name="man_juggling" unicode="&amp;#x1f939;&amp;#x2642;"/> from "man_juggling"<linebreak/>
- <emoji name="man_mechanic" unicode="&amp;#x1f468;&amp;#x1f527;"/> <emoji name="man_mechanic" unicode="&amp;#x1f468;&amp;#x1f527;"/> from "man_mechanic"<linebreak/>
- <emoji name="man_office_worker" unicode="&amp;#x1f468;&amp;#x1f4bc;"/> <emoji name="man_office_worker" unicode="&amp;#x1f468;&amp;#x1f4bc;"/> from "man_office_worker"<linebreak/>
- <emoji name="man_pilot" unicode="&amp;#x1f468;&amp;#x2708;"/> <emoji name="man_pilot" unicode="&amp;#x1f468;&amp;#x2708;"/> from "man_pilot"<linebreak/>
- <emoji name="man_playing_handball" unicode="&amp;#x1f93e;&amp;#x2642;"/> <emoji name="man_playing_handball" unicode="&amp;#x1f93e;&amp;#x2642;"/> from "man_playing_handball"<linebreak/>
- <emoji name="man_playing_water_polo" unicode="&amp;#x1f93d;&amp;#x2642;"/> <emoji name="man_playing_water_polo" unicode="&amp;#x1f93d;&amp;#x2642;"/> from "man_playing_water_polo"<linebreak/>
- <emoji name="man_scientist" unicode="&amp;#x1f468;&amp;#x1f52c;"/> <emoji name="man_scientist" unicode="&amp;#x1f468;&amp;#x1f52c;"/> from "man_scientist"<linebreak/>
- <emoji name="man_shrugging" unicode="&amp;#x1f937;&amp;#x2642;"/> <emoji name="man_shrugging" unicode="&amp;#x1f937;&amp;#x2642;"/> from "man_shrugging"<linebreak/>
- <emoji name="man_singer" unicode="&amp;#x1f468;&amp;#x1f3a4;"/> <emoji name="man_singer" unicode="&amp;#x1f468;&amp;#x1f3a4;"/> from "man_singer"<linebreak/>
- <emoji name="man_student" unicode="&amp;#x1f468;&amp;#x1f393;"/> <emoji name="man_student" unicode="&amp;#x1f468;&amp;#x1f393;"/> from "man_student"<linebreak/>
- <emoji name="man_teacher" unicode="&amp;#x1f468;&amp;#x1f3eb;"/> <emoji name="man_teacher" unicode="&amp;#x1f468;&amp;#x1f3eb;"/> from "man_teacher"<linebreak/>
- <emoji name="man_technologist" unicode="&amp;#x1f468;&amp;#x1f4bb;"/> <emoji name="man_technologist" unicode="&amp;#x1f468;&amp;#x1f4bb;"/> from "man_technologist"<linebreak/>
+ <emoji name="man_facepalming" unicode="&amp;#x1f926;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="man_facepalming" unicode="&amp;#x1f926;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "man_facepalming"<linebreak/>
+ <emoji name="man_factory_worker" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f3ed;"/> <emoji name="man_factory_worker" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f3ed;"/> from "man_factory_worker"<linebreak/>
+ <emoji name="man_farmer" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f33e;"/> <emoji name="man_farmer" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f33e;"/> from "man_farmer"<linebreak/>
+ <emoji name="man_feeding_baby" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f37c;"/> <emoji name="man_feeding_baby" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f37c;"/> from "man_feeding_baby"<linebreak/>
+ <emoji name="man_firefighter" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f692;"/> <emoji name="man_firefighter" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f692;"/> from "man_firefighter"<linebreak/>
+ <emoji name="man_health_worker" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x2695;&amp;#xfe0f;"/> <emoji name="man_health_worker" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x2695;&amp;#xfe0f;"/> from "man_health_worker"<linebreak/>
+ <emoji name="man_in_manual_wheelchair" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9bd;"/> <emoji name="man_in_manual_wheelchair" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9bd;"/> from "man_in_manual_wheelchair"<linebreak/>
+ <emoji name="man_in_motorized_wheelchair" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9bc;"/> <emoji name="man_in_motorized_wheelchair" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9bc;"/> from "man_in_motorized_wheelchair"<linebreak/>
+ <emoji name="man_in_tuxedo" unicode="&amp;#x1f935;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="man_in_tuxedo" unicode="&amp;#x1f935;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "man_in_tuxedo"<linebreak/>
+ <emoji name="man_judge" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x2696;&amp;#xfe0f;"/> <emoji name="man_judge" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x2696;&amp;#xfe0f;"/> from "man_judge"<linebreak/>
+ <emoji name="man_juggling" unicode="&amp;#x1f939;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="man_juggling" unicode="&amp;#x1f939;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "man_juggling"<linebreak/>
+ <emoji name="man_mechanic" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f527;"/> <emoji name="man_mechanic" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f527;"/> from "man_mechanic"<linebreak/>
+ <emoji name="man_office_worker" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f4bc;"/> <emoji name="man_office_worker" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f4bc;"/> from "man_office_worker"<linebreak/>
+ <emoji name="man_pilot" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x2708;&amp;#xfe0f;"/> <emoji name="man_pilot" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x2708;&amp;#xfe0f;"/> from "man_pilot"<linebreak/>
+ <emoji name="man_playing_handball" unicode="&amp;#x1f93e;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="man_playing_handball" unicode="&amp;#x1f93e;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "man_playing_handball"<linebreak/>
+ <emoji name="man_playing_water_polo" unicode="&amp;#x1f93d;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="man_playing_water_polo" unicode="&amp;#x1f93d;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "man_playing_water_polo"<linebreak/>
+ <emoji name="man_scientist" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f52c;"/> <emoji name="man_scientist" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f52c;"/> from "man_scientist"<linebreak/>
+ <emoji name="man_shrugging" unicode="&amp;#x1f937;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="man_shrugging" unicode="&amp;#x1f937;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "man_shrugging"<linebreak/>
+ <emoji name="man_singer" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f3a4;"/> <emoji name="man_singer" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f3a4;"/> from "man_singer"<linebreak/>
+ <emoji name="man_student" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f393;"/> <emoji name="man_student" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f393;"/> from "man_student"<linebreak/>
+ <emoji name="man_teacher" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f3eb;"/> <emoji name="man_teacher" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f3eb;"/> from "man_teacher"<linebreak/>
+ <emoji name="man_technologist" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f4bb;"/> <emoji name="man_technologist" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f4bb;"/> from "man_technologist"<linebreak/>
  <emoji name="man_with_gua_pi_mao" unicode="&amp;#x1f472;"/> <emoji name="man_with_gua_pi_mao" unicode="&amp;#x1f472;"/> from "man_with_gua_pi_mao"<linebreak/>
- <emoji name="man_with_turban" unicode="&amp;#x1f473;"/> <emoji name="man_with_turban" unicode="&amp;#x1f473;"/> from "man_with_turban"<linebreak/>
+ <emoji name="man_with_probing_cane" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9af;"/> <emoji name="man_with_probing_cane" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9af;"/> from "man_with_probing_cane"<linebreak/>
+ <emoji name="man_with_turban" unicode="&amp;#x1f473;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="man_with_turban" unicode="&amp;#x1f473;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "man_with_turban"<linebreak/>
+ <emoji name="man_with_veil" unicode="&amp;#x1f470;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="man_with_veil" unicode="&amp;#x1f470;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "man_with_veil"<linebreak/>
  <emoji name="mandarin" unicode="&amp;#x1f34a;"/> <emoji name="mandarin" unicode="&amp;#x1f34a;"/> from "mandarin"<linebreak/>
+ <emoji name="mango" unicode="&amp;#x1f96d;"/> <emoji name="mango" unicode="&amp;#x1f96d;"/> from "mango"<linebreak/>
  <emoji name="mans_shoe" unicode="&amp;#x1f45e;"/> <emoji name="mans_shoe" unicode="&amp;#x1f45e;"/> from "mans_shoe"<linebreak/>
  <emoji name="mantelpiece_clock" unicode="&amp;#x1f570;"/> <emoji name="mantelpiece_clock" unicode="&amp;#x1f570;"/> from "mantelpiece_clock"<linebreak/>
+ <emoji name="manual_wheelchair" unicode="&amp;#x1f9bd;"/> <emoji name="manual_wheelchair" unicode="&amp;#x1f9bd;"/> from "manual_wheelchair"<linebreak/>
  <emoji name="maple_leaf" unicode="&amp;#x1f341;"/> <emoji name="maple_leaf" unicode="&amp;#x1f341;"/> from "maple_leaf"<linebreak/>
  <emoji name="marshall_islands" unicode="&amp;#x1f1f2;&amp;#x1f1ed;"/> <emoji name="marshall_islands" unicode="&amp;#x1f1f2;&amp;#x1f1ed;"/> from "marshall_islands"<linebreak/>
  <emoji name="martial_arts_uniform" unicode="&amp;#x1f94b;"/> <emoji name="martial_arts_uniform" unicode="&amp;#x1f94b;"/> from "martial_arts_uniform"<linebreak/>
  <emoji name="martinique" unicode="&amp;#x1f1f2;&amp;#x1f1f6;"/> <emoji name="martinique" unicode="&amp;#x1f1f2;&amp;#x1f1f6;"/> from "martinique"<linebreak/>
  <emoji name="mask" unicode="&amp;#x1f637;"/> <emoji name="mask" unicode="&amp;#x1f637;"/> from "mask"<linebreak/>
  <emoji name="massage" unicode="&amp;#x1f486;"/> <emoji name="massage" unicode="&amp;#x1f486;"/> from "massage"<linebreak/>
- <emoji name="massage_man" unicode="&amp;#x1f486;&amp;#x2642;"/> <emoji name="massage_man" unicode="&amp;#x1f486;&amp;#x2642;"/> from "massage_man"<linebreak/>
- <emoji name="massage_woman" unicode="&amp;#x1f486;"/> <emoji name="massage_woman" unicode="&amp;#x1f486;"/> from "massage_woman"<linebreak/>
+ <emoji name="massage_man" unicode="&amp;#x1f486;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="massage_man" unicode="&amp;#x1f486;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "massage_man"<linebreak/>
+ <emoji name="massage_woman" unicode="&amp;#x1f486;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="massage_woman" unicode="&amp;#x1f486;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "massage_woman"<linebreak/>
+ <emoji name="mate" unicode="&amp;#x1f9c9;"/> <emoji name="mate" unicode="&amp;#x1f9c9;"/> from "mate"<linebreak/>
  <emoji name="mauritania" unicode="&amp;#x1f1f2;&amp;#x1f1f7;"/> <emoji name="mauritania" unicode="&amp;#x1f1f2;&amp;#x1f1f7;"/> from "mauritania"<linebreak/>
  <emoji name="mauritius" unicode="&amp;#x1f1f2;&amp;#x1f1fa;"/> <emoji name="mauritius" unicode="&amp;#x1f1f2;&amp;#x1f1fa;"/> from "mauritius"<linebreak/>
  <emoji name="mayotte" unicode="&amp;#x1f1fe;&amp;#x1f1f9;"/> <emoji name="mayotte" unicode="&amp;#x1f1fe;&amp;#x1f1f9;"/> from "mayotte"<linebreak/>
  <emoji name="meat_on_bone" unicode="&amp;#x1f356;"/> <emoji name="meat_on_bone" unicode="&amp;#x1f356;"/> from "meat_on_bone"<linebreak/>
+ <emoji name="mechanic" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f527;"/> <emoji name="mechanic" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f527;"/> from "mechanic"<linebreak/>
+ <emoji name="mechanical_arm" unicode="&amp;#x1f9be;"/> <emoji name="mechanical_arm" unicode="&amp;#x1f9be;"/> from "mechanical_arm"<linebreak/>
+ <emoji name="mechanical_leg" unicode="&amp;#x1f9bf;"/> <emoji name="mechanical_leg" unicode="&amp;#x1f9bf;"/> from "mechanical_leg"<linebreak/>
  <emoji name="medal_military" unicode="&amp;#x1f396;"/> <emoji name="medal_military" unicode="&amp;#x1f396;"/> from "medal_military"<linebreak/>
  <emoji name="medal_sports" unicode="&amp;#x1f3c5;"/> <emoji name="medal_sports" unicode="&amp;#x1f3c5;"/> from "medal_sports"<linebreak/>
+ <emoji name="medical_symbol" unicode="&amp;#x2695;"/> <emoji name="medical_symbol" unicode="&amp;#x2695;"/> from "medical_symbol"<linebreak/>
  <emoji name="mega" unicode="&amp;#x1f4e3;"/> <emoji name="mega" unicode="&amp;#x1f4e3;"/> from "mega"<linebreak/>
  <emoji name="melon" unicode="&amp;#x1f348;"/> <emoji name="melon" unicode="&amp;#x1f348;"/> from "melon"<linebreak/>
  <emoji name="memo" unicode="&amp;#x1f4dd;"/> <emoji name="memo" unicode="&amp;#x1f4dd;"/> from "memo"<linebreak/>
- <emoji name="men_wrestling" unicode="&amp;#x1f93c;&amp;#x2642;"/> <emoji name="men_wrestling" unicode="&amp;#x1f93c;&amp;#x2642;"/> from "men_wrestling"<linebreak/>
+ <emoji name="men_wrestling" unicode="&amp;#x1f93c;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="men_wrestling" unicode="&amp;#x1f93c;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "men_wrestling"<linebreak/>
+ <emoji name="mending_heart" unicode="&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1fa79;"/> <emoji name="mending_heart" unicode="&amp;#x2764;&amp;#xfe0f;&amp;#x200d;&amp;#x1fa79;"/> from "mending_heart"<linebreak/>
  <emoji name="menorah" unicode="&amp;#x1f54e;"/> <emoji name="menorah" unicode="&amp;#x1f54e;"/> from "menorah"<linebreak/>
  <emoji name="mens" unicode="&amp;#x1f6b9;"/> <emoji name="mens" unicode="&amp;#x1f6b9;"/> from "mens"<linebreak/>
+ <emoji name="mermaid" unicode="&amp;#x1f9dc;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="mermaid" unicode="&amp;#x1f9dc;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "mermaid"<linebreak/>
+ <emoji name="merman" unicode="&amp;#x1f9dc;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="merman" unicode="&amp;#x1f9dc;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "merman"<linebreak/>
+ <emoji name="merperson" unicode="&amp;#x1f9dc;"/> <emoji name="merperson" unicode="&amp;#x1f9dc;"/> from "merperson"<linebreak/>
  <emoji name="metal" unicode="&amp;#x1f918;"/> <emoji name="metal" unicode="&amp;#x1f918;"/> from "metal"<linebreak/>
  <emoji name="metro" unicode="&amp;#x1f687;"/> <emoji name="metro" unicode="&amp;#x1f687;"/> from "metro"<linebreak/>
  <emoji name="mexico" unicode="&amp;#x1f1f2;&amp;#x1f1fd;"/> <emoji name="mexico" unicode="&amp;#x1f1f2;&amp;#x1f1fd;"/> from "mexico"<linebreak/>
+ <emoji name="microbe" unicode="&amp;#x1f9a0;"/> <emoji name="microbe" unicode="&amp;#x1f9a0;"/> from "microbe"<linebreak/>
  <emoji name="micronesia" unicode="&amp;#x1f1eb;&amp;#x1f1f2;"/> <emoji name="micronesia" unicode="&amp;#x1f1eb;&amp;#x1f1f2;"/> from "micronesia"<linebreak/>
  <emoji name="microphone" unicode="&amp;#x1f3a4;"/> <emoji name="microphone" unicode="&amp;#x1f3a4;"/> from "microphone"<linebreak/>
  <emoji name="microscope" unicode="&amp;#x1f52c;"/> <emoji name="microscope" unicode="&amp;#x1f52c;"/> from "microscope"<linebreak/>
  <emoji name="middle_finger" unicode="&amp;#x1f595;"/> <emoji name="middle_finger" unicode="&amp;#x1f595;"/> from "middle_finger"<linebreak/>
+ <emoji name="military_helmet" unicode="&amp;#x1fa96;"/> <emoji name="military_helmet" unicode="&amp;#x1fa96;"/> from "military_helmet"<linebreak/>
  <emoji name="milk_glass" unicode="&amp;#x1f95b;"/> <emoji name="milk_glass" unicode="&amp;#x1f95b;"/> from "milk_glass"<linebreak/>
  <emoji name="milky_way" unicode="&amp;#x1f30c;"/> <emoji name="milky_way" unicode="&amp;#x1f30c;"/> from "milky_way"<linebreak/>
  <emoji name="minibus" unicode="&amp;#x1f690;"/> <emoji name="minibus" unicode="&amp;#x1f690;"/> from "minibus"<linebreak/>
  <emoji name="minidisc" unicode="&amp;#x1f4bd;"/> <emoji name="minidisc" unicode="&amp;#x1f4bd;"/> from "minidisc"<linebreak/>
+ <emoji name="mirror" unicode="&amp;#x1fa9e;"/> <emoji name="mirror" unicode="&amp;#x1fa9e;"/> from "mirror"<linebreak/>
  <emoji name="mobile_phone_off" unicode="&amp;#x1f4f4;"/> <emoji name="mobile_phone_off" unicode="&amp;#x1f4f4;"/> from "mobile_phone_off"<linebreak/>
  <emoji name="moldova" unicode="&amp;#x1f1f2;&amp;#x1f1e9;"/> <emoji name="moldova" unicode="&amp;#x1f1f2;&amp;#x1f1e9;"/> from "moldova"<linebreak/>
  <emoji name="monaco" unicode="&amp;#x1f1f2;&amp;#x1f1e8;"/> <emoji name="monaco" unicode="&amp;#x1f1f2;&amp;#x1f1e8;"/> from "monaco"<linebreak/>
  <emoji name="mongolia" unicode="&amp;#x1f1f2;&amp;#x1f1f3;"/> <emoji name="mongolia" unicode="&amp;#x1f1f2;&amp;#x1f1f3;"/> from "mongolia"<linebreak/>
  <emoji name="monkey" unicode="&amp;#x1f412;"/> <emoji name="monkey" unicode="&amp;#x1f412;"/> from "monkey"<linebreak/>
  <emoji name="monkey_face" unicode="&amp;#x1f435;"/> <emoji name="monkey_face" unicode="&amp;#x1f435;"/> from "monkey_face"<linebreak/>
+ <emoji name="monocle_face" unicode="&amp;#x1f9d0;"/> <emoji name="monocle_face" unicode="&amp;#x1f9d0;"/> from "monocle_face"<linebreak/>
  <emoji name="monorail" unicode="&amp;#x1f69d;"/> <emoji name="monorail" unicode="&amp;#x1f69d;"/> from "monorail"<linebreak/>
  <emoji name="montenegro" unicode="&amp;#x1f1f2;&amp;#x1f1ea;"/> <emoji name="montenegro" unicode="&amp;#x1f1f2;&amp;#x1f1ea;"/> from "montenegro"<linebreak/>
  <emoji name="montserrat" unicode="&amp;#x1f1f2;&amp;#x1f1f8;"/> <emoji name="montserrat" unicode="&amp;#x1f1f2;&amp;#x1f1f8;"/> from "montserrat"<linebreak/>
  <emoji name="moon" unicode="&amp;#x1f314;"/> <emoji name="moon" unicode="&amp;#x1f314;"/> from "moon"<linebreak/>
+ <emoji name="moon_cake" unicode="&amp;#x1f96e;"/> <emoji name="moon_cake" unicode="&amp;#x1f96e;"/> from "moon_cake"<linebreak/>
  <emoji name="morocco" unicode="&amp;#x1f1f2;&amp;#x1f1e6;"/> <emoji name="morocco" unicode="&amp;#x1f1f2;&amp;#x1f1e6;"/> from "morocco"<linebreak/>
  <emoji name="mortar_board" unicode="&amp;#x1f393;"/> <emoji name="mortar_board" unicode="&amp;#x1f393;"/> from "mortar_board"<linebreak/>
  <emoji name="mosque" unicode="&amp;#x1f54c;"/> <emoji name="mosque" unicode="&amp;#x1f54c;"/> from "mosque"<linebreak/>
+ <emoji name="mosquito" unicode="&amp;#x1f99f;"/> <emoji name="mosquito" unicode="&amp;#x1f99f;"/> from "mosquito"<linebreak/>
  <emoji name="motor_boat" unicode="&amp;#x1f6e5;"/> <emoji name="motor_boat" unicode="&amp;#x1f6e5;"/> from "motor_boat"<linebreak/>
  <emoji name="motor_scooter" unicode="&amp;#x1f6f5;"/> <emoji name="motor_scooter" unicode="&amp;#x1f6f5;"/> from "motor_scooter"<linebreak/>
  <emoji name="motorcycle" unicode="&amp;#x1f3cd;"/> <emoji name="motorcycle" unicode="&amp;#x1f3cd;"/> from "motorcycle"<linebreak/>
+ <emoji name="motorized_wheelchair" unicode="&amp;#x1f9bc;"/> <emoji name="motorized_wheelchair" unicode="&amp;#x1f9bc;"/> from "motorized_wheelchair"<linebreak/>
  <emoji name="motorway" unicode="&amp;#x1f6e3;"/> <emoji name="motorway" unicode="&amp;#x1f6e3;"/> from "motorway"<linebreak/>
  <emoji name="mount_fuji" unicode="&amp;#x1f5fb;"/> <emoji name="mount_fuji" unicode="&amp;#x1f5fb;"/> from "mount_fuji"<linebreak/>
  <emoji name="mountain" unicode="&amp;#x26f0;"/> <emoji name="mountain" unicode="&amp;#x26f0;"/> from "mountain"<linebreak/>
  <emoji name="mountain_bicyclist" unicode="&amp;#x1f6b5;"/> <emoji name="mountain_bicyclist" unicode="&amp;#x1f6b5;"/> from "mountain_bicyclist"<linebreak/>
- <emoji name="mountain_biking_man" unicode="&amp;#x1f6b5;"/> <emoji name="mountain_biking_man" unicode="&amp;#x1f6b5;"/> from "mountain_biking_man"<linebreak/>
- <emoji name="mountain_biking_woman" unicode="&amp;#x1f6b5;&amp;#x2640;"/> <emoji name="mountain_biking_woman" unicode="&amp;#x1f6b5;&amp;#x2640;"/> from "mountain_biking_woman"<linebreak/>
+ <emoji name="mountain_biking_man" unicode="&amp;#x1f6b5;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="mountain_biking_man" unicode="&amp;#x1f6b5;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "mountain_biking_man"<linebreak/>
+ <emoji name="mountain_biking_woman" unicode="&amp;#x1f6b5;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="mountain_biking_woman" unicode="&amp;#x1f6b5;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "mountain_biking_woman"<linebreak/>
  <emoji name="mountain_cableway" unicode="&amp;#x1f6a0;"/> <emoji name="mountain_cableway" unicode="&amp;#x1f6a0;"/> from "mountain_cableway"<linebreak/>
  <emoji name="mountain_railway" unicode="&amp;#x1f69e;"/> <emoji name="mountain_railway" unicode="&amp;#x1f69e;"/> from "mountain_railway"<linebreak/>
  <emoji name="mountain_snow" unicode="&amp;#x1f3d4;"/> <emoji name="mountain_snow" unicode="&amp;#x1f3d4;"/> from "mountain_snow"<linebreak/>
  <emoji name="mouse" unicode="&amp;#x1f42d;"/> <emoji name="mouse" unicode="&amp;#x1f42d;"/> from "mouse"<linebreak/>
  <emoji name="mouse2" unicode="&amp;#x1f401;"/> <emoji name="mouse2" unicode="&amp;#x1f401;"/> from "mouse2"<linebreak/>
+ <emoji name="mouse_trap" unicode="&amp;#x1faa4;"/> <emoji name="mouse_trap" unicode="&amp;#x1faa4;"/> from "mouse_trap"<linebreak/>
  <emoji name="movie_camera" unicode="&amp;#x1f3a5;"/> <emoji name="movie_camera" unicode="&amp;#x1f3a5;"/> from "movie_camera"<linebreak/>
  <emoji name="moyai" unicode="&amp;#x1f5ff;"/> <emoji name="moyai" unicode="&amp;#x1f5ff;"/> from "moyai"<linebreak/>
  <emoji name="mozambique" unicode="&amp;#x1f1f2;&amp;#x1f1ff;"/> <emoji name="mozambique" unicode="&amp;#x1f1f2;&amp;#x1f1ff;"/> from "mozambique"<linebreak/>
  <emoji name="musical_note" unicode="&amp;#x1f3b5;"/> <emoji name="musical_note" unicode="&amp;#x1f3b5;"/> from "musical_note"<linebreak/>
  <emoji name="musical_score" unicode="&amp;#x1f3bc;"/> <emoji name="musical_score" unicode="&amp;#x1f3bc;"/> from "musical_score"<linebreak/>
  <emoji name="mute" unicode="&amp;#x1f507;"/> <emoji name="mute" unicode="&amp;#x1f507;"/> from "mute"<linebreak/>
+ <emoji name="mx_claus" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f384;"/> <emoji name="mx_claus" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f384;"/> from "mx_claus"<linebreak/>
  <emoji name="myanmar" unicode="&amp;#x1f1f2;&amp;#x1f1f2;"/> <emoji name="myanmar" unicode="&amp;#x1f1f2;&amp;#x1f1f2;"/> from "myanmar"<linebreak/>
  <emoji name="nail_care" unicode="&amp;#x1f485;"/> <emoji name="nail_care" unicode="&amp;#x1f485;"/> from "nail_care"<linebreak/>
  <emoji name="name_badge" unicode="&amp;#x1f4db;"/> <emoji name="name_badge" unicode="&amp;#x1f4db;"/> from "name_badge"<linebreak/>
  <emoji name="national_park" unicode="&amp;#x1f3de;"/> <emoji name="national_park" unicode="&amp;#x1f3de;"/> from "national_park"<linebreak/>
  <emoji name="nauru" unicode="&amp;#x1f1f3;&amp;#x1f1f7;"/> <emoji name="nauru" unicode="&amp;#x1f1f3;&amp;#x1f1f7;"/> from "nauru"<linebreak/>
  <emoji name="nauseated_face" unicode="&amp;#x1f922;"/> <emoji name="nauseated_face" unicode="&amp;#x1f922;"/> from "nauseated_face"<linebreak/>
+ <emoji name="nazar_amulet" unicode="&amp;#x1f9ff;"/> <emoji name="nazar_amulet" unicode="&amp;#x1f9ff;"/> from "nazar_amulet"<linebreak/>
  <emoji name="necktie" unicode="&amp;#x1f454;"/> <emoji name="necktie" unicode="&amp;#x1f454;"/> from "necktie"<linebreak/>
  <emoji name="negative_squared_cross_mark" unicode="&amp;#x274e;"/> <emoji name="negative_squared_cross_mark" unicode="&amp;#x274e;"/> from "negative_squared_cross_mark"<linebreak/>
  <emoji name="nepal" unicode="&amp;#x1f1f3;&amp;#x1f1f5;"/> <emoji name="nepal" unicode="&amp;#x1f1f3;&amp;#x1f1f5;"/> from "nepal"<linebreak/>
  <emoji name="nerd_face" unicode="&amp;#x1f913;"/> <emoji name="nerd_face" unicode="&amp;#x1f913;"/> from "nerd_face"<linebreak/>
+ <emoji name="nesting_dolls" unicode="&amp;#x1fa86;"/> <emoji name="nesting_dolls" unicode="&amp;#x1fa86;"/> from "nesting_dolls"<linebreak/>
  <emoji name="netherlands" unicode="&amp;#x1f1f3;&amp;#x1f1f1;"/> <emoji name="netherlands" unicode="&amp;#x1f1f3;&amp;#x1f1f1;"/> from "netherlands"<linebreak/>
  <emoji name="neutral_face" unicode="&amp;#x1f610;"/> <emoji name="neutral_face" unicode="&amp;#x1f610;"/> from "neutral_face"<linebreak/>
  <emoji name="new" unicode="&amp;#x1f195;"/> <emoji name="new" unicode="&amp;#x1f195;"/> from "new"<linebreak/>
  <emoji name="newspaper_roll" unicode="&amp;#x1f5de;"/> <emoji name="newspaper_roll" unicode="&amp;#x1f5de;"/> from "newspaper_roll"<linebreak/>
  <emoji name="next_track_button" unicode="&amp;#x23ed;"/> <emoji name="next_track_button" unicode="&amp;#x23ed;"/> from "next_track_button"<linebreak/>
  <emoji name="ng" unicode="&amp;#x1f196;"/> <emoji name="ng" unicode="&amp;#x1f196;"/> from "ng"<linebreak/>
- <emoji name="ng_man" unicode="&amp;#x1f645;&amp;#x2642;"/> <emoji name="ng_man" unicode="&amp;#x1f645;&amp;#x2642;"/> from "ng_man"<linebreak/>
- <emoji name="ng_woman" unicode="&amp;#x1f645;"/> <emoji name="ng_woman" unicode="&amp;#x1f645;"/> from "ng_woman"<linebreak/>
+ <emoji name="ng_man" unicode="&amp;#x1f645;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="ng_man" unicode="&amp;#x1f645;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "ng_man"<linebreak/>
+ <emoji name="ng_woman" unicode="&amp;#x1f645;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="ng_woman" unicode="&amp;#x1f645;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "ng_woman"<linebreak/>
  <emoji name="nicaragua" unicode="&amp;#x1f1f3;&amp;#x1f1ee;"/> <emoji name="nicaragua" unicode="&amp;#x1f1f3;&amp;#x1f1ee;"/> from "nicaragua"<linebreak/>
  <emoji name="niger" unicode="&amp;#x1f1f3;&amp;#x1f1ea;"/> <emoji name="niger" unicode="&amp;#x1f1f3;&amp;#x1f1ea;"/> from "niger"<linebreak/>
  <emoji name="nigeria" unicode="&amp;#x1f1f3;&amp;#x1f1ec;"/> <emoji name="nigeria" unicode="&amp;#x1f1f3;&amp;#x1f1ec;"/> from "nigeria"<linebreak/>
  <emoji name="night_with_stars" unicode="&amp;#x1f303;"/> <emoji name="night_with_stars" unicode="&amp;#x1f303;"/> from "night_with_stars"<linebreak/>
- <emoji name="nine" unicode="&amp;#x0039;&amp;#x20e3;"/> <emoji name="nine" unicode="&amp;#x0039;&amp;#x20e3;"/> from "nine"<linebreak/>
+ <emoji name="nine" unicode="&amp;#x0039;&amp;#xfe0f;&amp;#x20e3;"/> <emoji name="nine" unicode="&amp;#x0039;&amp;#xfe0f;&amp;#x20e3;"/> from "nine"<linebreak/>
+ <emoji name="ninja" unicode="&amp;#x1f977;"/> <emoji name="ninja" unicode="&amp;#x1f977;"/> from "ninja"<linebreak/>
  <emoji name="niue" unicode="&amp;#x1f1f3;&amp;#x1f1fa;"/> <emoji name="niue" unicode="&amp;#x1f1f3;&amp;#x1f1fa;"/> from "niue"<linebreak/>
  <emoji name="no_bell" unicode="&amp;#x1f515;"/> <emoji name="no_bell" unicode="&amp;#x1f515;"/> from "no_bell"<linebreak/>
  <emoji name="no_bicycles" unicode="&amp;#x1f6b3;"/> <emoji name="no_bicycles" unicode="&amp;#x1f6b3;"/> from "no_bicycles"<linebreak/>
  <emoji name="no_entry" unicode="&amp;#x26d4;"/> <emoji name="no_entry" unicode="&amp;#x26d4;"/> from "no_entry"<linebreak/>
  <emoji name="no_entry_sign" unicode="&amp;#x1f6ab;"/> <emoji name="no_entry_sign" unicode="&amp;#x1f6ab;"/> from "no_entry_sign"<linebreak/>
  <emoji name="no_good" unicode="&amp;#x1f645;"/> <emoji name="no_good" unicode="&amp;#x1f645;"/> from "no_good"<linebreak/>
- <emoji name="no_good_man" unicode="&amp;#x1f645;&amp;#x2642;"/> <emoji name="no_good_man" unicode="&amp;#x1f645;&amp;#x2642;"/> from "no_good_man"<linebreak/>
- <emoji name="no_good_woman" unicode="&amp;#x1f645;"/> <emoji name="no_good_woman" unicode="&amp;#x1f645;"/> from "no_good_woman"<linebreak/>
+ <emoji name="no_good_man" unicode="&amp;#x1f645;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="no_good_man" unicode="&amp;#x1f645;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "no_good_man"<linebreak/>
+ <emoji name="no_good_woman" unicode="&amp;#x1f645;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="no_good_woman" unicode="&amp;#x1f645;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "no_good_woman"<linebreak/>
  <emoji name="no_mobile_phones" unicode="&amp;#x1f4f5;"/> <emoji name="no_mobile_phones" unicode="&amp;#x1f4f5;"/> from "no_mobile_phones"<linebreak/>
  <emoji name="no_mouth" unicode="&amp;#x1f636;"/> <emoji name="no_mouth" unicode="&amp;#x1f636;"/> from "no_mouth"<linebreak/>
  <emoji name="no_pedestrians" unicode="&amp;#x1f6b7;"/> <emoji name="no_pedestrians" unicode="&amp;#x1f6b7;"/> from "no_pedestrians"<linebreak/>
  <emoji name="octopus" unicode="&amp;#x1f419;"/> <emoji name="octopus" unicode="&amp;#x1f419;"/> from "octopus"<linebreak/>
  <emoji name="oden" unicode="&amp;#x1f362;"/> <emoji name="oden" unicode="&amp;#x1f362;"/> from "oden"<linebreak/>
  <emoji name="office" unicode="&amp;#x1f3e2;"/> <emoji name="office" unicode="&amp;#x1f3e2;"/> from "office"<linebreak/>
+ <emoji name="office_worker" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f4bc;"/> <emoji name="office_worker" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f4bc;"/> from "office_worker"<linebreak/>
  <emoji name="oil_drum" unicode="&amp;#x1f6e2;"/> <emoji name="oil_drum" unicode="&amp;#x1f6e2;"/> from "oil_drum"<linebreak/>
  <emoji name="ok" unicode="&amp;#x1f197;"/> <emoji name="ok" unicode="&amp;#x1f197;"/> from "ok"<linebreak/>
  <emoji name="ok_hand" unicode="&amp;#x1f44c;"/> <emoji name="ok_hand" unicode="&amp;#x1f44c;"/> from "ok_hand"<linebreak/>
- <emoji name="ok_man" unicode="&amp;#x1f646;&amp;#x2642;"/> <emoji name="ok_man" unicode="&amp;#x1f646;&amp;#x2642;"/> from "ok_man"<linebreak/>
- <emoji name="ok_woman" unicode="&amp;#x1f646;"/> <emoji name="ok_woman" unicode="&amp;#x1f646;"/> from "ok_woman"<linebreak/>
+ <emoji name="ok_man" unicode="&amp;#x1f646;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="ok_man" unicode="&amp;#x1f646;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "ok_man"<linebreak/>
+ <emoji name="ok_person" unicode="&amp;#x1f646;"/> <emoji name="ok_person" unicode="&amp;#x1f646;"/> from "ok_person"<linebreak/>
+ <emoji name="ok_woman" unicode="&amp;#x1f646;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="ok_woman" unicode="&amp;#x1f646;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "ok_woman"<linebreak/>
  <emoji name="old_key" unicode="&amp;#x1f5dd;"/> <emoji name="old_key" unicode="&amp;#x1f5dd;"/> from "old_key"<linebreak/>
+ <emoji name="older_adult" unicode="&amp;#x1f9d3;"/> <emoji name="older_adult" unicode="&amp;#x1f9d3;"/> from "older_adult"<linebreak/>
  <emoji name="older_man" unicode="&amp;#x1f474;"/> <emoji name="older_man" unicode="&amp;#x1f474;"/> from "older_man"<linebreak/>
  <emoji name="older_woman" unicode="&amp;#x1f475;"/> <emoji name="older_woman" unicode="&amp;#x1f475;"/> from "older_woman"<linebreak/>
+ <emoji name="olive" unicode="&amp;#x1fad2;"/> <emoji name="olive" unicode="&amp;#x1fad2;"/> from "olive"<linebreak/>
  <emoji name="om" unicode="&amp;#x1f549;"/> <emoji name="om" unicode="&amp;#x1f549;"/> from "om"<linebreak/>
  <emoji name="oman" unicode="&amp;#x1f1f4;&amp;#x1f1f2;"/> <emoji name="oman" unicode="&amp;#x1f1f4;&amp;#x1f1f2;"/> from "oman"<linebreak/>
  <emoji name="on" unicode="&amp;#x1f51b;"/> <emoji name="on" unicode="&amp;#x1f51b;"/> from "on"<linebreak/>
  <emoji name="oncoming_bus" unicode="&amp;#x1f68d;"/> <emoji name="oncoming_bus" unicode="&amp;#x1f68d;"/> from "oncoming_bus"<linebreak/>
  <emoji name="oncoming_police_car" unicode="&amp;#x1f694;"/> <emoji name="oncoming_police_car" unicode="&amp;#x1f694;"/> from "oncoming_police_car"<linebreak/>
  <emoji name="oncoming_taxi" unicode="&amp;#x1f696;"/> <emoji name="oncoming_taxi" unicode="&amp;#x1f696;"/> from "oncoming_taxi"<linebreak/>
- <emoji name="one" unicode="&amp;#x0031;&amp;#x20e3;"/> <emoji name="one" unicode="&amp;#x0031;&amp;#x20e3;"/> from "one"<linebreak/>
+ <emoji name="one" unicode="&amp;#x0031;&amp;#xfe0f;&amp;#x20e3;"/> <emoji name="one" unicode="&amp;#x0031;&amp;#xfe0f;&amp;#x20e3;"/> from "one"<linebreak/>
+ <emoji name="one_piece_swimsuit" unicode="&amp;#x1fa71;"/> <emoji name="one_piece_swimsuit" unicode="&amp;#x1fa71;"/> from "one_piece_swimsuit"<linebreak/>
+ <emoji name="onion" unicode="&amp;#x1f9c5;"/> <emoji name="onion" unicode="&amp;#x1f9c5;"/> from "onion"<linebreak/>
  <emoji name="open_book" unicode="&amp;#x1f4d6;"/> <emoji name="open_book" unicode="&amp;#x1f4d6;"/> from "open_book"<linebreak/>
  <emoji name="open_file_folder" unicode="&amp;#x1f4c2;"/> <emoji name="open_file_folder" unicode="&amp;#x1f4c2;"/> from "open_file_folder"<linebreak/>
  <emoji name="open_hands" unicode="&amp;#x1f450;"/> <emoji name="open_hands" unicode="&amp;#x1f450;"/> from "open_hands"<linebreak/>
- <emoji name="open_mouth" unicode="&amp;#x1f62e;"/> <emoji name="open_mouth" unicode="&amp;#x1f62e;"/> from "open_mouth"<linebreak/>
+ <emoji name="open_mouth" unicode="&amp;#x1f62e;&amp;#x200d;&amp;#x1f4a8;"/> <emoji name="open_mouth" unicode="&amp;#x1f62e;&amp;#x200d;&amp;#x1f4a8;"/> from "open_mouth"<linebreak/>
  <emoji name="open_umbrella" unicode="&amp;#x2602;"/> <emoji name="open_umbrella" unicode="&amp;#x2602;"/> from "open_umbrella"<linebreak/>
  <emoji name="ophiuchus" unicode="&amp;#x26ce;"/> <emoji name="ophiuchus" unicode="&amp;#x26ce;"/> from "ophiuchus"<linebreak/>
  <emoji name="orange" unicode="&amp;#x1f34a;"/> <emoji name="orange" unicode="&amp;#x1f34a;"/> from "orange"<linebreak/>
  <emoji name="orange_book" unicode="&amp;#x1f4d9;"/> <emoji name="orange_book" unicode="&amp;#x1f4d9;"/> from "orange_book"<linebreak/>
+ <emoji name="orange_circle" unicode="&amp;#x1f7e0;"/> <emoji name="orange_circle" unicode="&amp;#x1f7e0;"/> from "orange_circle"<linebreak/>
+ <emoji name="orange_heart" unicode="&amp;#x1f9e1;"/> <emoji name="orange_heart" unicode="&amp;#x1f9e1;"/> from "orange_heart"<linebreak/>
+ <emoji name="orange_square" unicode="&amp;#x1f7e7;"/> <emoji name="orange_square" unicode="&amp;#x1f7e7;"/> from "orange_square"<linebreak/>
+ <emoji name="orangutan" unicode="&amp;#x1f9a7;"/> <emoji name="orangutan" unicode="&amp;#x1f9a7;"/> from "orangutan"<linebreak/>
  <emoji name="orthodox_cross" unicode="&amp;#x2626;"/> <emoji name="orthodox_cross" unicode="&amp;#x2626;"/> from "orthodox_cross"<linebreak/>
+ <emoji name="otter" unicode="&amp;#x1f9a6;"/> <emoji name="otter" unicode="&amp;#x1f9a6;"/> from "otter"<linebreak/>
  <emoji name="outbox_tray" unicode="&amp;#x1f4e4;"/> <emoji name="outbox_tray" unicode="&amp;#x1f4e4;"/> from "outbox_tray"<linebreak/>
  <emoji name="owl" unicode="&amp;#x1f989;"/> <emoji name="owl" unicode="&amp;#x1f989;"/> from "owl"<linebreak/>
  <emoji name="ox" unicode="&amp;#x1f402;"/> <emoji name="ox" unicode="&amp;#x1f402;"/> from "ox"<linebreak/>
+ <emoji name="oyster" unicode="&amp;#x1f9aa;"/> <emoji name="oyster" unicode="&amp;#x1f9aa;"/> from "oyster"<linebreak/>
  <emoji name="package" unicode="&amp;#x1f4e6;"/> <emoji name="package" unicode="&amp;#x1f4e6;"/> from "package"<linebreak/>
  <emoji name="page_facing_up" unicode="&amp;#x1f4c4;"/> <emoji name="page_facing_up" unicode="&amp;#x1f4c4;"/> from "page_facing_up"<linebreak/>
  <emoji name="page_with_curl" unicode="&amp;#x1f4c3;"/> <emoji name="page_with_curl" unicode="&amp;#x1f4c3;"/> from "page_with_curl"<linebreak/>
  <emoji name="palau" unicode="&amp;#x1f1f5;&amp;#x1f1fc;"/> <emoji name="palau" unicode="&amp;#x1f1f5;&amp;#x1f1fc;"/> from "palau"<linebreak/>
  <emoji name="palestinian_territories" unicode="&amp;#x1f1f5;&amp;#x1f1f8;"/> <emoji name="palestinian_territories" unicode="&amp;#x1f1f5;&amp;#x1f1f8;"/> from "palestinian_territories"<linebreak/>
  <emoji name="palm_tree" unicode="&amp;#x1f334;"/> <emoji name="palm_tree" unicode="&amp;#x1f334;"/> from "palm_tree"<linebreak/>
+ <emoji name="palms_up_together" unicode="&amp;#x1f932;"/> <emoji name="palms_up_together" unicode="&amp;#x1f932;"/> from "palms_up_together"<linebreak/>
  <emoji name="panama" unicode="&amp;#x1f1f5;&amp;#x1f1e6;"/> <emoji name="panama" unicode="&amp;#x1f1f5;&amp;#x1f1e6;"/> from "panama"<linebreak/>
  <emoji name="pancakes" unicode="&amp;#x1f95e;"/> <emoji name="pancakes" unicode="&amp;#x1f95e;"/> from "pancakes"<linebreak/>
  <emoji name="panda_face" unicode="&amp;#x1f43c;"/> <emoji name="panda_face" unicode="&amp;#x1f43c;"/> from "panda_face"<linebreak/>
  <emoji name="paperclip" unicode="&amp;#x1f4ce;"/> <emoji name="paperclip" unicode="&amp;#x1f4ce;"/> from "paperclip"<linebreak/>
  <emoji name="paperclips" unicode="&amp;#x1f587;"/> <emoji name="paperclips" unicode="&amp;#x1f587;"/> from "paperclips"<linebreak/>
  <emoji name="papua_new_guinea" unicode="&amp;#x1f1f5;&amp;#x1f1ec;"/> <emoji name="papua_new_guinea" unicode="&amp;#x1f1f5;&amp;#x1f1ec;"/> from "papua_new_guinea"<linebreak/>
+ <emoji name="parachute" unicode="&amp;#x1fa82;"/> <emoji name="parachute" unicode="&amp;#x1fa82;"/> from "parachute"<linebreak/>
  <emoji name="paraguay" unicode="&amp;#x1f1f5;&amp;#x1f1fe;"/> <emoji name="paraguay" unicode="&amp;#x1f1f5;&amp;#x1f1fe;"/> from "paraguay"<linebreak/>
  <emoji name="parasol_on_ground" unicode="&amp;#x26f1;"/> <emoji name="parasol_on_ground" unicode="&amp;#x26f1;"/> from "parasol_on_ground"<linebreak/>
  <emoji name="parking" unicode="&amp;#x1f17f;"/> <emoji name="parking" unicode="&amp;#x1f17f;"/> from "parking"<linebreak/>
+ <emoji name="parrot" unicode="&amp;#x1f99c;"/> <emoji name="parrot" unicode="&amp;#x1f99c;"/> from "parrot"<linebreak/>
  <emoji name="part_alternation_mark" unicode="&amp;#x303d;"/> <emoji name="part_alternation_mark" unicode="&amp;#x303d;"/> from "part_alternation_mark"<linebreak/>
  <emoji name="partly_sunny" unicode="&amp;#x26c5;"/> <emoji name="partly_sunny" unicode="&amp;#x26c5;"/> from "partly_sunny"<linebreak/>
+ <emoji name="partying_face" unicode="&amp;#x1f973;"/> <emoji name="partying_face" unicode="&amp;#x1f973;"/> from "partying_face"<linebreak/>
  <emoji name="passenger_ship" unicode="&amp;#x1f6f3;"/> <emoji name="passenger_ship" unicode="&amp;#x1f6f3;"/> from "passenger_ship"<linebreak/>
  <emoji name="passport_control" unicode="&amp;#x1f6c2;"/> <emoji name="passport_control" unicode="&amp;#x1f6c2;"/> from "passport_control"<linebreak/>
  <emoji name="pause_button" unicode="&amp;#x23f8;"/> <emoji name="pause_button" unicode="&amp;#x23f8;"/> from "pause_button"<linebreak/>
  <emoji name="paw_prints" unicode="&amp;#x1f43e;"/> <emoji name="paw_prints" unicode="&amp;#x1f43e;"/> from "paw_prints"<linebreak/>
  <emoji name="peace_symbol" unicode="&amp;#x262e;"/> <emoji name="peace_symbol" unicode="&amp;#x262e;"/> from "peace_symbol"<linebreak/>
  <emoji name="peach" unicode="&amp;#x1f351;"/> <emoji name="peach" unicode="&amp;#x1f351;"/> from "peach"<linebreak/>
+ <emoji name="peacock" unicode="&amp;#x1f99a;"/> <emoji name="peacock" unicode="&amp;#x1f99a;"/> from "peacock"<linebreak/>
  <emoji name="peanuts" unicode="&amp;#x1f95c;"/> <emoji name="peanuts" unicode="&amp;#x1f95c;"/> from "peanuts"<linebreak/>
  <emoji name="pear" unicode="&amp;#x1f350;"/> <emoji name="pear" unicode="&amp;#x1f350;"/> from "pear"<linebreak/>
  <emoji name="pen" unicode="&amp;#x1f58a;"/> <emoji name="pen" unicode="&amp;#x1f58a;"/> from "pen"<linebreak/>
  <emoji name="pencil2" unicode="&amp;#x270f;"/> <emoji name="pencil2" unicode="&amp;#x270f;"/> from "pencil2"<linebreak/>
  <emoji name="penguin" unicode="&amp;#x1f427;"/> <emoji name="penguin" unicode="&amp;#x1f427;"/> from "penguin"<linebreak/>
  <emoji name="pensive" unicode="&amp;#x1f614;"/> <emoji name="pensive" unicode="&amp;#x1f614;"/> from "pensive"<linebreak/>
+ <emoji name="people_holding_hands" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f91d;&amp;#x200d;&amp;#x1f9d1;"/> <emoji name="people_holding_hands" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f91d;&amp;#x200d;&amp;#x1f9d1;"/> from "people_holding_hands"<linebreak/>
+ <emoji name="people_hugging" unicode="&amp;#x1fac2;"/> <emoji name="people_hugging" unicode="&amp;#x1fac2;"/> from "people_hugging"<linebreak/>
  <emoji name="performing_arts" unicode="&amp;#x1f3ad;"/> <emoji name="performing_arts" unicode="&amp;#x1f3ad;"/> from "performing_arts"<linebreak/>
  <emoji name="persevere" unicode="&amp;#x1f623;"/> <emoji name="persevere" unicode="&amp;#x1f623;"/> from "persevere"<linebreak/>
+ <emoji name="person_bald" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9b2;"/> <emoji name="person_bald" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9b2;"/> from "person_bald"<linebreak/>
+ <emoji name="person_curly_hair" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9b1;"/> <emoji name="person_curly_hair" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9b1;"/> from "person_curly_hair"<linebreak/>
+ <emoji name="person_feeding_baby" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f37c;"/> <emoji name="person_feeding_baby" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f37c;"/> from "person_feeding_baby"<linebreak/>
  <emoji name="person_fencing" unicode="&amp;#x1f93a;"/> <emoji name="person_fencing" unicode="&amp;#x1f93a;"/> from "person_fencing"<linebreak/>
- <emoji name="person_frowning" unicode="&amp;#x1f64d;"/> <emoji name="person_frowning" unicode="&amp;#x1f64d;"/> from "person_frowning"<linebreak/>
- <emoji name="person_with_blond_hair" unicode="&amp;#x1f471;"/> <emoji name="person_with_blond_hair" unicode="&amp;#x1f471;"/> from "person_with_blond_hair"<linebreak/>
- <emoji name="person_with_pouting_face" unicode="&amp;#x1f64e;"/> <emoji name="person_with_pouting_face" unicode="&amp;#x1f64e;"/> from "person_with_pouting_face"<linebreak/>
+ <emoji name="person_in_manual_wheelchair" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9bd;"/> <emoji name="person_in_manual_wheelchair" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9bd;"/> from "person_in_manual_wheelchair"<linebreak/>
+ <emoji name="person_in_motorized_wheelchair" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9bc;"/> <emoji name="person_in_motorized_wheelchair" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9bc;"/> from "person_in_motorized_wheelchair"<linebreak/>
+ <emoji name="person_in_tuxedo" unicode="&amp;#x1f935;"/> <emoji name="person_in_tuxedo" unicode="&amp;#x1f935;"/> from "person_in_tuxedo"<linebreak/>
+ <emoji name="person_red_hair" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9b0;"/> <emoji name="person_red_hair" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9b0;"/> from "person_red_hair"<linebreak/>
+ <emoji name="person_white_hair" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9b3;"/> <emoji name="person_white_hair" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9b3;"/> from "person_white_hair"<linebreak/>
+ <emoji name="person_with_probing_cane" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9af;"/> <emoji name="person_with_probing_cane" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f9af;"/> from "person_with_probing_cane"<linebreak/>
+ <emoji name="person_with_turban" unicode="&amp;#x1f473;"/> <emoji name="person_with_turban" unicode="&amp;#x1f473;"/> from "person_with_turban"<linebreak/>
+ <emoji name="person_with_veil" unicode="&amp;#x1f470;"/> <emoji name="person_with_veil" unicode="&amp;#x1f470;"/> from "person_with_veil"<linebreak/>
  <emoji name="peru" unicode="&amp;#x1f1f5;&amp;#x1f1ea;"/> <emoji name="peru" unicode="&amp;#x1f1f5;&amp;#x1f1ea;"/> from "peru"<linebreak/>
+ <emoji name="petri_dish" unicode="&amp;#x1f9eb;"/> <emoji name="petri_dish" unicode="&amp;#x1f9eb;"/> from "petri_dish"<linebreak/>
  <emoji name="philippines" unicode="&amp;#x1f1f5;&amp;#x1f1ed;"/> <emoji name="philippines" unicode="&amp;#x1f1f5;&amp;#x1f1ed;"/> from "philippines"<linebreak/>
  <emoji name="phone" unicode="&amp;#x260e;"/> <emoji name="phone" unicode="&amp;#x260e;"/> from "phone"<linebreak/>
  <emoji name="pick" unicode="&amp;#x26cf;"/> <emoji name="pick" unicode="&amp;#x26cf;"/> from "pick"<linebreak/>
+ <emoji name="pickup_truck" unicode="&amp;#x1f6fb;"/> <emoji name="pickup_truck" unicode="&amp;#x1f6fb;"/> from "pickup_truck"<linebreak/>
+ <emoji name="pie" unicode="&amp;#x1f967;"/> <emoji name="pie" unicode="&amp;#x1f967;"/> from "pie"<linebreak/>
  <emoji name="pig" unicode="&amp;#x1f437;"/> <emoji name="pig" unicode="&amp;#x1f437;"/> from "pig"<linebreak/>
  <emoji name="pig2" unicode="&amp;#x1f416;"/> <emoji name="pig2" unicode="&amp;#x1f416;"/> from "pig2"<linebreak/>
  <emoji name="pig_nose" unicode="&amp;#x1f43d;"/> <emoji name="pig_nose" unicode="&amp;#x1f43d;"/> from "pig_nose"<linebreak/>
  <emoji name="pill" unicode="&amp;#x1f48a;"/> <emoji name="pill" unicode="&amp;#x1f48a;"/> from "pill"<linebreak/>
+ <emoji name="pilot" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x2708;&amp;#xfe0f;"/> <emoji name="pilot" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x2708;&amp;#xfe0f;"/> from "pilot"<linebreak/>
+ <emoji name="pinata" unicode="&amp;#x1fa85;"/> <emoji name="pinata" unicode="&amp;#x1fa85;"/> from "pinata"<linebreak/>
+ <emoji name="pinched_fingers" unicode="&amp;#x1f90c;"/> <emoji name="pinched_fingers" unicode="&amp;#x1f90c;"/> from "pinched_fingers"<linebreak/>
+ <emoji name="pinching_hand" unicode="&amp;#x1f90f;"/> <emoji name="pinching_hand" unicode="&amp;#x1f90f;"/> from "pinching_hand"<linebreak/>
  <emoji name="pineapple" unicode="&amp;#x1f34d;"/> <emoji name="pineapple" unicode="&amp;#x1f34d;"/> from "pineapple"<linebreak/>
  <emoji name="ping_pong" unicode="&amp;#x1f3d3;"/> <emoji name="ping_pong" unicode="&amp;#x1f3d3;"/> from "ping_pong"<linebreak/>
+ <emoji name="pirate_flag" unicode="&amp;#x1f3f4;&amp;#x200d;&amp;#x2620;&amp;#xfe0f;"/> <emoji name="pirate_flag" unicode="&amp;#x1f3f4;&amp;#x200d;&amp;#x2620;&amp;#xfe0f;"/> from "pirate_flag"<linebreak/>
  <emoji name="pisces" unicode="&amp;#x2653;"/> <emoji name="pisces" unicode="&amp;#x2653;"/> from "pisces"<linebreak/>
  <emoji name="pitcairn_islands" unicode="&amp;#x1f1f5;&amp;#x1f1f3;"/> <emoji name="pitcairn_islands" unicode="&amp;#x1f1f5;&amp;#x1f1f3;"/> from "pitcairn_islands"<linebreak/>
  <emoji name="pizza" unicode="&amp;#x1f355;"/> <emoji name="pizza" unicode="&amp;#x1f355;"/> from "pizza"<linebreak/>
+ <emoji name="placard" unicode="&amp;#x1faa7;"/> <emoji name="placard" unicode="&amp;#x1faa7;"/> from "placard"<linebreak/>
  <emoji name="place_of_worship" unicode="&amp;#x1f6d0;"/> <emoji name="place_of_worship" unicode="&amp;#x1f6d0;"/> from "place_of_worship"<linebreak/>
  <emoji name="plate_with_cutlery" unicode="&amp;#x1f37d;"/> <emoji name="plate_with_cutlery" unicode="&amp;#x1f37d;"/> from "plate_with_cutlery"<linebreak/>
  <emoji name="play_or_pause_button" unicode="&amp;#x23ef;"/> <emoji name="play_or_pause_button" unicode="&amp;#x23ef;"/> from "play_or_pause_button"<linebreak/>
+ <emoji name="pleading_face" unicode="&amp;#x1f97a;"/> <emoji name="pleading_face" unicode="&amp;#x1f97a;"/> from "pleading_face"<linebreak/>
+ <emoji name="plunger" unicode="&amp;#x1faa0;"/> <emoji name="plunger" unicode="&amp;#x1faa0;"/> from "plunger"<linebreak/>
  <emoji name="point_down" unicode="&amp;#x1f447;"/> <emoji name="point_down" unicode="&amp;#x1f447;"/> from "point_down"<linebreak/>
  <emoji name="point_left" unicode="&amp;#x1f448;"/> <emoji name="point_left" unicode="&amp;#x1f448;"/> from "point_left"<linebreak/>
  <emoji name="point_right" unicode="&amp;#x1f449;"/> <emoji name="point_right" unicode="&amp;#x1f449;"/> from "point_right"<linebreak/>
  <emoji name="point_up" unicode="&amp;#x261d;"/> <emoji name="point_up" unicode="&amp;#x261d;"/> from "point_up"<linebreak/>
  <emoji name="point_up_2" unicode="&amp;#x1f446;"/> <emoji name="point_up_2" unicode="&amp;#x1f446;"/> from "point_up_2"<linebreak/>
  <emoji name="poland" unicode="&amp;#x1f1f5;&amp;#x1f1f1;"/> <emoji name="poland" unicode="&amp;#x1f1f5;&amp;#x1f1f1;"/> from "poland"<linebreak/>
+ <emoji name="polar_bear" unicode="&amp;#x1f43b;&amp;#x200d;&amp;#x2744;&amp;#xfe0f;"/> <emoji name="polar_bear" unicode="&amp;#x1f43b;&amp;#x200d;&amp;#x2744;&amp;#xfe0f;"/> from "polar_bear"<linebreak/>
  <emoji name="police_car" unicode="&amp;#x1f693;"/> <emoji name="police_car" unicode="&amp;#x1f693;"/> from "police_car"<linebreak/>
- <emoji name="policeman" unicode="&amp;#x1f46e;"/> <emoji name="policeman" unicode="&amp;#x1f46e;"/> from "policeman"<linebreak/>
- <emoji name="policewoman" unicode="&amp;#x1f46e;&amp;#x2640;"/> <emoji name="policewoman" unicode="&amp;#x1f46e;&amp;#x2640;"/> from "policewoman"<linebreak/>
+ <emoji name="police_officer" unicode="&amp;#x1f46e;"/> <emoji name="police_officer" unicode="&amp;#x1f46e;"/> from "police_officer"<linebreak/>
+ <emoji name="policeman" unicode="&amp;#x1f46e;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="policeman" unicode="&amp;#x1f46e;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "policeman"<linebreak/>
+ <emoji name="policewoman" unicode="&amp;#x1f46e;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="policewoman" unicode="&amp;#x1f46e;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "policewoman"<linebreak/>
  <emoji name="poodle" unicode="&amp;#x1f429;"/> <emoji name="poodle" unicode="&amp;#x1f429;"/> from "poodle"<linebreak/>
  <emoji name="poop" unicode="&amp;#x1f4a9;"/> <emoji name="poop" unicode="&amp;#x1f4a9;"/> from "poop"<linebreak/>
  <emoji name="popcorn" unicode="&amp;#x1f37f;"/> <emoji name="popcorn" unicode="&amp;#x1f37f;"/> from "popcorn"<linebreak/>
  <emoji name="postbox" unicode="&amp;#x1f4ee;"/> <emoji name="postbox" unicode="&amp;#x1f4ee;"/> from "postbox"<linebreak/>
  <emoji name="potable_water" unicode="&amp;#x1f6b0;"/> <emoji name="potable_water" unicode="&amp;#x1f6b0;"/> from "potable_water"<linebreak/>
  <emoji name="potato" unicode="&amp;#x1f954;"/> <emoji name="potato" unicode="&amp;#x1f954;"/> from "potato"<linebreak/>
+ <emoji name="potted_plant" unicode="&amp;#x1fab4;"/> <emoji name="potted_plant" unicode="&amp;#x1fab4;"/> from "potted_plant"<linebreak/>
  <emoji name="pouch" unicode="&amp;#x1f45d;"/> <emoji name="pouch" unicode="&amp;#x1f45d;"/> from "pouch"<linebreak/>
  <emoji name="poultry_leg" unicode="&amp;#x1f357;"/> <emoji name="poultry_leg" unicode="&amp;#x1f357;"/> from "poultry_leg"<linebreak/>
  <emoji name="pound" unicode="&amp;#x1f4b7;"/> <emoji name="pound" unicode="&amp;#x1f4b7;"/> from "pound"<linebreak/>
  <emoji name="pout" unicode="&amp;#x1f621;"/> <emoji name="pout" unicode="&amp;#x1f621;"/> from "pout"<linebreak/>
  <emoji name="pouting_cat" unicode="&amp;#x1f63e;"/> <emoji name="pouting_cat" unicode="&amp;#x1f63e;"/> from "pouting_cat"<linebreak/>
- <emoji name="pouting_man" unicode="&amp;#x1f64e;&amp;#x2642;"/> <emoji name="pouting_man" unicode="&amp;#x1f64e;&amp;#x2642;"/> from "pouting_man"<linebreak/>
- <emoji name="pouting_woman" unicode="&amp;#x1f64e;"/> <emoji name="pouting_woman" unicode="&amp;#x1f64e;"/> from "pouting_woman"<linebreak/>
+ <emoji name="pouting_face" unicode="&amp;#x1f64e;"/> <emoji name="pouting_face" unicode="&amp;#x1f64e;"/> from "pouting_face"<linebreak/>
+ <emoji name="pouting_man" unicode="&amp;#x1f64e;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="pouting_man" unicode="&amp;#x1f64e;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "pouting_man"<linebreak/>
+ <emoji name="pouting_woman" unicode="&amp;#x1f64e;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="pouting_woman" unicode="&amp;#x1f64e;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "pouting_woman"<linebreak/>
  <emoji name="pray" unicode="&amp;#x1f64f;"/> <emoji name="pray" unicode="&amp;#x1f64f;"/> from "pray"<linebreak/>
  <emoji name="prayer_beads" unicode="&amp;#x1f4ff;"/> <emoji name="prayer_beads" unicode="&amp;#x1f4ff;"/> from "prayer_beads"<linebreak/>
  <emoji name="pregnant_woman" unicode="&amp;#x1f930;"/> <emoji name="pregnant_woman" unicode="&amp;#x1f930;"/> from "pregnant_woman"<linebreak/>
+ <emoji name="pretzel" unicode="&amp;#x1f968;"/> <emoji name="pretzel" unicode="&amp;#x1f968;"/> from "pretzel"<linebreak/>
  <emoji name="previous_track_button" unicode="&amp;#x23ee;"/> <emoji name="previous_track_button" unicode="&amp;#x23ee;"/> from "previous_track_button"<linebreak/>
  <emoji name="prince" unicode="&amp;#x1f934;"/> <emoji name="prince" unicode="&amp;#x1f934;"/> from "prince"<linebreak/>
  <emoji name="princess" unicode="&amp;#x1f478;"/> <emoji name="princess" unicode="&amp;#x1f478;"/> from "princess"<linebreak/>
  <emoji name="printer" unicode="&amp;#x1f5a8;"/> <emoji name="printer" unicode="&amp;#x1f5a8;"/> from "printer"<linebreak/>
+ <emoji name="probing_cane" unicode="&amp;#x1f9af;"/> <emoji name="probing_cane" unicode="&amp;#x1f9af;"/> from "probing_cane"<linebreak/>
  <emoji name="puerto_rico" unicode="&amp;#x1f1f5;&amp;#x1f1f7;"/> <emoji name="puerto_rico" unicode="&amp;#x1f1f5;&amp;#x1f1f7;"/> from "puerto_rico"<linebreak/>
  <emoji name="punch" unicode="&amp;#x1f44a;"/> <emoji name="punch" unicode="&amp;#x1f44a;"/> from "punch"<linebreak/>
+ <emoji name="purple_circle" unicode="&amp;#x1f7e3;"/> <emoji name="purple_circle" unicode="&amp;#x1f7e3;"/> from "purple_circle"<linebreak/>
  <emoji name="purple_heart" unicode="&amp;#x1f49c;"/> <emoji name="purple_heart" unicode="&amp;#x1f49c;"/> from "purple_heart"<linebreak/>
+ <emoji name="purple_square" unicode="&amp;#x1f7ea;"/> <emoji name="purple_square" unicode="&amp;#x1f7ea;"/> from "purple_square"<linebreak/>
  <emoji name="purse" unicode="&amp;#x1f45b;"/> <emoji name="purse" unicode="&amp;#x1f45b;"/> from "purse"<linebreak/>
  <emoji name="pushpin" unicode="&amp;#x1f4cc;"/> <emoji name="pushpin" unicode="&amp;#x1f4cc;"/> from "pushpin"<linebreak/>
  <emoji name="put_litter_in_its_place" unicode="&amp;#x1f6ae;"/> <emoji name="put_litter_in_its_place" unicode="&amp;#x1f6ae;"/> from "put_litter_in_its_place"<linebreak/>
  <emoji name="question" unicode="&amp;#x2753;"/> <emoji name="question" unicode="&amp;#x2753;"/> from "question"<linebreak/>
  <emoji name="rabbit" unicode="&amp;#x1f430;"/> <emoji name="rabbit" unicode="&amp;#x1f430;"/> from "rabbit"<linebreak/>
  <emoji name="rabbit2" unicode="&amp;#x1f407;"/> <emoji name="rabbit2" unicode="&amp;#x1f407;"/> from "rabbit2"<linebreak/>
+ <emoji name="raccoon" unicode="&amp;#x1f99d;"/> <emoji name="raccoon" unicode="&amp;#x1f99d;"/> from "raccoon"<linebreak/>
  <emoji name="racehorse" unicode="&amp;#x1f40e;"/> <emoji name="racehorse" unicode="&amp;#x1f40e;"/> from "racehorse"<linebreak/>
  <emoji name="racing_car" unicode="&amp;#x1f3ce;"/> <emoji name="racing_car" unicode="&amp;#x1f3ce;"/> from "racing_car"<linebreak/>
  <emoji name="radio" unicode="&amp;#x1f4fb;"/> <emoji name="radio" unicode="&amp;#x1f4fb;"/> from "radio"<linebreak/>
  <emoji name="railway_car" unicode="&amp;#x1f683;"/> <emoji name="railway_car" unicode="&amp;#x1f683;"/> from "railway_car"<linebreak/>
  <emoji name="railway_track" unicode="&amp;#x1f6e4;"/> <emoji name="railway_track" unicode="&amp;#x1f6e4;"/> from "railway_track"<linebreak/>
  <emoji name="rainbow" unicode="&amp;#x1f308;"/> <emoji name="rainbow" unicode="&amp;#x1f308;"/> from "rainbow"<linebreak/>
- <emoji name="rainbow_flag" unicode="&amp;#x1f3f3;&amp;#x1f308;"/> <emoji name="rainbow_flag" unicode="&amp;#x1f3f3;&amp;#x1f308;"/> from "rainbow_flag"<linebreak/>
+ <emoji name="rainbow_flag" unicode="&amp;#x1f3f3;&amp;#xfe0f;&amp;#x200d;&amp;#x1f308;"/> <emoji name="rainbow_flag" unicode="&amp;#x1f3f3;&amp;#xfe0f;&amp;#x200d;&amp;#x1f308;"/> from "rainbow_flag"<linebreak/>
  <emoji name="raised_back_of_hand" unicode="&amp;#x1f91a;"/> <emoji name="raised_back_of_hand" unicode="&amp;#x1f91a;"/> from "raised_back_of_hand"<linebreak/>
+ <emoji name="raised_eyebrow" unicode="&amp;#x1f928;"/> <emoji name="raised_eyebrow" unicode="&amp;#x1f928;"/> from "raised_eyebrow"<linebreak/>
  <emoji name="raised_hand" unicode="&amp;#x270b;"/> <emoji name="raised_hand" unicode="&amp;#x270b;"/> from "raised_hand"<linebreak/>
  <emoji name="raised_hand_with_fingers_splayed" unicode="&amp;#x1f590;"/> <emoji name="raised_hand_with_fingers_splayed" unicode="&amp;#x1f590;"/> from "raised_hand_with_fingers_splayed"<linebreak/>
  <emoji name="raised_hands" unicode="&amp;#x1f64c;"/> <emoji name="raised_hands" unicode="&amp;#x1f64c;"/> from "raised_hands"<linebreak/>
  <emoji name="raising_hand" unicode="&amp;#x1f64b;"/> <emoji name="raising_hand" unicode="&amp;#x1f64b;"/> from "raising_hand"<linebreak/>
- <emoji name="raising_hand_man" unicode="&amp;#x1f64b;&amp;#x2642;"/> <emoji name="raising_hand_man" unicode="&amp;#x1f64b;&amp;#x2642;"/> from "raising_hand_man"<linebreak/>
- <emoji name="raising_hand_woman" unicode="&amp;#x1f64b;"/> <emoji name="raising_hand_woman" unicode="&amp;#x1f64b;"/> from "raising_hand_woman"<linebreak/>
+ <emoji name="raising_hand_man" unicode="&amp;#x1f64b;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="raising_hand_man" unicode="&amp;#x1f64b;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "raising_hand_man"<linebreak/>
+ <emoji name="raising_hand_woman" unicode="&amp;#x1f64b;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="raising_hand_woman" unicode="&amp;#x1f64b;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "raising_hand_woman"<linebreak/>
  <emoji name="ram" unicode="&amp;#x1f40f;"/> <emoji name="ram" unicode="&amp;#x1f40f;"/> from "ram"<linebreak/>
  <emoji name="ramen" unicode="&amp;#x1f35c;"/> <emoji name="ramen" unicode="&amp;#x1f35c;"/> from "ramen"<linebreak/>
  <emoji name="rat" unicode="&amp;#x1f400;"/> <emoji name="rat" unicode="&amp;#x1f400;"/> from "rat"<linebreak/>
+ <emoji name="razor" unicode="&amp;#x1fa92;"/> <emoji name="razor" unicode="&amp;#x1fa92;"/> from "razor"<linebreak/>
+ <emoji name="receipt" unicode="&amp;#x1f9fe;"/> <emoji name="receipt" unicode="&amp;#x1f9fe;"/> from "receipt"<linebreak/>
  <emoji name="record_button" unicode="&amp;#x23fa;"/> <emoji name="record_button" unicode="&amp;#x23fa;"/> from "record_button"<linebreak/>
  <emoji name="recycle" unicode="&amp;#x267b;"/> <emoji name="recycle" unicode="&amp;#x267b;"/> from "recycle"<linebreak/>
  <emoji name="red_car" unicode="&amp;#x1f697;"/> <emoji name="red_car" unicode="&amp;#x1f697;"/> from "red_car"<linebreak/>
  <emoji name="red_circle" unicode="&amp;#x1f534;"/> <emoji name="red_circle" unicode="&amp;#x1f534;"/> from "red_circle"<linebreak/>
+ <emoji name="red_envelope" unicode="&amp;#x1f9e7;"/> <emoji name="red_envelope" unicode="&amp;#x1f9e7;"/> from "red_envelope"<linebreak/>
+ <emoji name="red_haired_man" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9b0;"/> <emoji name="red_haired_man" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9b0;"/> from "red_haired_man"<linebreak/>
+ <emoji name="red_haired_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9b0;"/> <emoji name="red_haired_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9b0;"/> from "red_haired_woman"<linebreak/>
+ <emoji name="red_square" unicode="&amp;#x1f7e5;"/> <emoji name="red_square" unicode="&amp;#x1f7e5;"/> from "red_square"<linebreak/>
  <emoji name="registered" unicode="&amp;#x00ae;"/> <emoji name="registered" unicode="&amp;#x00ae;"/> from "registered"<linebreak/>
  <emoji name="relaxed" unicode="&amp;#x263a;"/> <emoji name="relaxed" unicode="&amp;#x263a;"/> from "relaxed"<linebreak/>
  <emoji name="relieved" unicode="&amp;#x1f60c;"/> <emoji name="relieved" unicode="&amp;#x1f60c;"/> from "relieved"<linebreak/>
  <emoji name="rice_scene" unicode="&amp;#x1f391;"/> <emoji name="rice_scene" unicode="&amp;#x1f391;"/> from "rice_scene"<linebreak/>
  <emoji name="right_anger_bubble" unicode="&amp;#x1f5ef;"/> <emoji name="right_anger_bubble" unicode="&amp;#x1f5ef;"/> from "right_anger_bubble"<linebreak/>
  <emoji name="ring" unicode="&amp;#x1f48d;"/> <emoji name="ring" unicode="&amp;#x1f48d;"/> from "ring"<linebreak/>
+ <emoji name="ringed_planet" unicode="&amp;#x1fa90;"/> <emoji name="ringed_planet" unicode="&amp;#x1fa90;"/> from "ringed_planet"<linebreak/>
  <emoji name="robot" unicode="&amp;#x1f916;"/> <emoji name="robot" unicode="&amp;#x1f916;"/> from "robot"<linebreak/>
+ <emoji name="rock" unicode="&amp;#x1faa8;"/> <emoji name="rock" unicode="&amp;#x1faa8;"/> from "rock"<linebreak/>
  <emoji name="rocket" unicode="&amp;#x1f680;"/> <emoji name="rocket" unicode="&amp;#x1f680;"/> from "rocket"<linebreak/>
  <emoji name="rofl" unicode="&amp;#x1f923;"/> <emoji name="rofl" unicode="&amp;#x1f923;"/> from "rofl"<linebreak/>
  <emoji name="roll_eyes" unicode="&amp;#x1f644;"/> <emoji name="roll_eyes" unicode="&amp;#x1f644;"/> from "roll_eyes"<linebreak/>
+ <emoji name="roll_of_paper" unicode="&amp;#x1f9fb;"/> <emoji name="roll_of_paper" unicode="&amp;#x1f9fb;"/> from "roll_of_paper"<linebreak/>
  <emoji name="roller_coaster" unicode="&amp;#x1f3a2;"/> <emoji name="roller_coaster" unicode="&amp;#x1f3a2;"/> from "roller_coaster"<linebreak/>
+ <emoji name="roller_skate" unicode="&amp;#x1f6fc;"/> <emoji name="roller_skate" unicode="&amp;#x1f6fc;"/> from "roller_skate"<linebreak/>
  <emoji name="romania" unicode="&amp;#x1f1f7;&amp;#x1f1f4;"/> <emoji name="romania" unicode="&amp;#x1f1f7;&amp;#x1f1f4;"/> from "romania"<linebreak/>
  <emoji name="rooster" unicode="&amp;#x1f413;"/> <emoji name="rooster" unicode="&amp;#x1f413;"/> from "rooster"<linebreak/>
  <emoji name="rose" unicode="&amp;#x1f339;"/> <emoji name="rose" unicode="&amp;#x1f339;"/> from "rose"<linebreak/>
  <emoji name="rotating_light" unicode="&amp;#x1f6a8;"/> <emoji name="rotating_light" unicode="&amp;#x1f6a8;"/> from "rotating_light"<linebreak/>
  <emoji name="round_pushpin" unicode="&amp;#x1f4cd;"/> <emoji name="round_pushpin" unicode="&amp;#x1f4cd;"/> from "round_pushpin"<linebreak/>
  <emoji name="rowboat" unicode="&amp;#x1f6a3;"/> <emoji name="rowboat" unicode="&amp;#x1f6a3;"/> from "rowboat"<linebreak/>
- <emoji name="rowing_man" unicode="&amp;#x1f6a3;"/> <emoji name="rowing_man" unicode="&amp;#x1f6a3;"/> from "rowing_man"<linebreak/>
- <emoji name="rowing_woman" unicode="&amp;#x1f6a3;&amp;#x2640;"/> <emoji name="rowing_woman" unicode="&amp;#x1f6a3;&amp;#x2640;"/> from "rowing_woman"<linebreak/>
+ <emoji name="rowing_man" unicode="&amp;#x1f6a3;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="rowing_man" unicode="&amp;#x1f6a3;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "rowing_man"<linebreak/>
+ <emoji name="rowing_woman" unicode="&amp;#x1f6a3;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="rowing_woman" unicode="&amp;#x1f6a3;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "rowing_woman"<linebreak/>
  <emoji name="ru" unicode="&amp;#x1f1f7;&amp;#x1f1fa;"/> <emoji name="ru" unicode="&amp;#x1f1f7;&amp;#x1f1fa;"/> from "ru"<linebreak/>
  <emoji name="rugby_football" unicode="&amp;#x1f3c9;"/> <emoji name="rugby_football" unicode="&amp;#x1f3c9;"/> from "rugby_football"<linebreak/>
  <emoji name="runner" unicode="&amp;#x1f3c3;"/> <emoji name="runner" unicode="&amp;#x1f3c3;"/> from "runner"<linebreak/>
  <emoji name="running" unicode="&amp;#x1f3c3;"/> <emoji name="running" unicode="&amp;#x1f3c3;"/> from "running"<linebreak/>
- <emoji name="running_man" unicode="&amp;#x1f3c3;"/> <emoji name="running_man" unicode="&amp;#x1f3c3;"/> from "running_man"<linebreak/>
+ <emoji name="running_man" unicode="&amp;#x1f3c3;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="running_man" unicode="&amp;#x1f3c3;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "running_man"<linebreak/>
  <emoji name="running_shirt_with_sash" unicode="&amp;#x1f3bd;"/> <emoji name="running_shirt_with_sash" unicode="&amp;#x1f3bd;"/> from "running_shirt_with_sash"<linebreak/>
- <emoji name="running_woman" unicode="&amp;#x1f3c3;&amp;#x2640;"/> <emoji name="running_woman" unicode="&amp;#x1f3c3;&amp;#x2640;"/> from "running_woman"<linebreak/>
+ <emoji name="running_woman" unicode="&amp;#x1f3c3;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="running_woman" unicode="&amp;#x1f3c3;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "running_woman"<linebreak/>
  <emoji name="rwanda" unicode="&amp;#x1f1f7;&amp;#x1f1fc;"/> <emoji name="rwanda" unicode="&amp;#x1f1f7;&amp;#x1f1fc;"/> from "rwanda"<linebreak/>
  <emoji name="sa" unicode="&amp;#x1f202;"/> <emoji name="sa" unicode="&amp;#x1f202;"/> from "sa"<linebreak/>
+ <emoji name="safety_pin" unicode="&amp;#x1f9f7;"/> <emoji name="safety_pin" unicode="&amp;#x1f9f7;"/> from "safety_pin"<linebreak/>
+ <emoji name="safety_vest" unicode="&amp;#x1f9ba;"/> <emoji name="safety_vest" unicode="&amp;#x1f9ba;"/> from "safety_vest"<linebreak/>
  <emoji name="sagittarius" unicode="&amp;#x2650;"/> <emoji name="sagittarius" unicode="&amp;#x2650;"/> from "sagittarius"<linebreak/>
  <emoji name="sailboat" unicode="&amp;#x26f5;"/> <emoji name="sailboat" unicode="&amp;#x26f5;"/> from "sailboat"<linebreak/>
  <emoji name="sake" unicode="&amp;#x1f376;"/> <emoji name="sake" unicode="&amp;#x1f376;"/> from "sake"<linebreak/>
+ <emoji name="salt" unicode="&amp;#x1f9c2;"/> <emoji name="salt" unicode="&amp;#x1f9c2;"/> from "salt"<linebreak/>
  <emoji name="samoa" unicode="&amp;#x1f1fc;&amp;#x1f1f8;"/> <emoji name="samoa" unicode="&amp;#x1f1fc;&amp;#x1f1f8;"/> from "samoa"<linebreak/>
  <emoji name="san_marino" unicode="&amp;#x1f1f8;&amp;#x1f1f2;"/> <emoji name="san_marino" unicode="&amp;#x1f1f8;&amp;#x1f1f2;"/> from "san_marino"<linebreak/>
  <emoji name="sandal" unicode="&amp;#x1f461;"/> <emoji name="sandal" unicode="&amp;#x1f461;"/> from "sandal"<linebreak/>
+ <emoji name="sandwich" unicode="&amp;#x1f96a;"/> <emoji name="sandwich" unicode="&amp;#x1f96a;"/> from "sandwich"<linebreak/>
  <emoji name="santa" unicode="&amp;#x1f385;"/> <emoji name="santa" unicode="&amp;#x1f385;"/> from "santa"<linebreak/>
  <emoji name="sao_tome_principe" unicode="&amp;#x1f1f8;&amp;#x1f1f9;"/> <emoji name="sao_tome_principe" unicode="&amp;#x1f1f8;&amp;#x1f1f9;"/> from "sao_tome_principe"<linebreak/>
+ <emoji name="sari" unicode="&amp;#x1f97b;"/> <emoji name="sari" unicode="&amp;#x1f97b;"/> from "sari"<linebreak/>
+ <emoji name="sassy_man" unicode="&amp;#x1f481;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="sassy_man" unicode="&amp;#x1f481;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "sassy_man"<linebreak/>
+ <emoji name="sassy_woman" unicode="&amp;#x1f481;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="sassy_woman" unicode="&amp;#x1f481;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "sassy_woman"<linebreak/>
  <emoji name="satellite" unicode="&amp;#x1f4e1;"/> <emoji name="satellite" unicode="&amp;#x1f4e1;"/> from "satellite"<linebreak/>
  <emoji name="satisfied" unicode="&amp;#x1f606;"/> <emoji name="satisfied" unicode="&amp;#x1f606;"/> from "satisfied"<linebreak/>
  <emoji name="saudi_arabia" unicode="&amp;#x1f1f8;&amp;#x1f1e6;"/> <emoji name="saudi_arabia" unicode="&amp;#x1f1f8;&amp;#x1f1e6;"/> from "saudi_arabia"<linebreak/>
+ <emoji name="sauna_man" unicode="&amp;#x1f9d6;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="sauna_man" unicode="&amp;#x1f9d6;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "sauna_man"<linebreak/>
+ <emoji name="sauna_person" unicode="&amp;#x1f9d6;"/> <emoji name="sauna_person" unicode="&amp;#x1f9d6;"/> from "sauna_person"<linebreak/>
+ <emoji name="sauna_woman" unicode="&amp;#x1f9d6;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="sauna_woman" unicode="&amp;#x1f9d6;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "sauna_woman"<linebreak/>
+ <emoji name="sauropod" unicode="&amp;#x1f995;"/> <emoji name="sauropod" unicode="&amp;#x1f995;"/> from "sauropod"<linebreak/>
  <emoji name="saxophone" unicode="&amp;#x1f3b7;"/> <emoji name="saxophone" unicode="&amp;#x1f3b7;"/> from "saxophone"<linebreak/>
+ <emoji name="scarf" unicode="&amp;#x1f9e3;"/> <emoji name="scarf" unicode="&amp;#x1f9e3;"/> from "scarf"<linebreak/>
  <emoji name="school" unicode="&amp;#x1f3eb;"/> <emoji name="school" unicode="&amp;#x1f3eb;"/> from "school"<linebreak/>
  <emoji name="school_satchel" unicode="&amp;#x1f392;"/> <emoji name="school_satchel" unicode="&amp;#x1f392;"/> from "school_satchel"<linebreak/>
+ <emoji name="scientist" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f52c;"/> <emoji name="scientist" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f52c;"/> from "scientist"<linebreak/>
  <emoji name="scissors" unicode="&amp;#x2702;"/> <emoji name="scissors" unicode="&amp;#x2702;"/> from "scissors"<linebreak/>
  <emoji name="scorpion" unicode="&amp;#x1f982;"/> <emoji name="scorpion" unicode="&amp;#x1f982;"/> from "scorpion"<linebreak/>
  <emoji name="scorpius" unicode="&amp;#x264f;"/> <emoji name="scorpius" unicode="&amp;#x264f;"/> from "scorpius"<linebreak/>
+ <emoji name="scotland" unicode="&amp;#x1f3f4;&amp;#xe0067;&amp;#xe0062;&amp;#xe0073;&amp;#xe0063;&amp;#xe0074;&amp;#xe007f;"/> <emoji name="scotland" unicode="&amp;#x1f3f4;&amp;#xe0067;&amp;#xe0062;&amp;#xe0073;&amp;#xe0063;&amp;#xe0074;&amp;#xe007f;"/> from "scotland"<linebreak/>
  <emoji name="scream" unicode="&amp;#x1f631;"/> <emoji name="scream" unicode="&amp;#x1f631;"/> from "scream"<linebreak/>
  <emoji name="scream_cat" unicode="&amp;#x1f640;"/> <emoji name="scream_cat" unicode="&amp;#x1f640;"/> from "scream_cat"<linebreak/>
+ <emoji name="screwdriver" unicode="&amp;#x1fa9b;"/> <emoji name="screwdriver" unicode="&amp;#x1fa9b;"/> from "screwdriver"<linebreak/>
  <emoji name="scroll" unicode="&amp;#x1f4dc;"/> <emoji name="scroll" unicode="&amp;#x1f4dc;"/> from "scroll"<linebreak/>
+ <emoji name="seal" unicode="&amp;#x1f9ad;"/> <emoji name="seal" unicode="&amp;#x1f9ad;"/> from "seal"<linebreak/>
  <emoji name="seat" unicode="&amp;#x1f4ba;"/> <emoji name="seat" unicode="&amp;#x1f4ba;"/> from "seat"<linebreak/>
  <emoji name="secret" unicode="&amp;#x3299;"/> <emoji name="secret" unicode="&amp;#x3299;"/> from "secret"<linebreak/>
  <emoji name="see_no_evil" unicode="&amp;#x1f648;"/> <emoji name="see_no_evil" unicode="&amp;#x1f648;"/> from "see_no_evil"<linebreak/>
  <emoji name="selfie" unicode="&amp;#x1f933;"/> <emoji name="selfie" unicode="&amp;#x1f933;"/> from "selfie"<linebreak/>
  <emoji name="senegal" unicode="&amp;#x1f1f8;&amp;#x1f1f3;"/> <emoji name="senegal" unicode="&amp;#x1f1f8;&amp;#x1f1f3;"/> from "senegal"<linebreak/>
  <emoji name="serbia" unicode="&amp;#x1f1f7;&amp;#x1f1f8;"/> <emoji name="serbia" unicode="&amp;#x1f1f7;&amp;#x1f1f8;"/> from "serbia"<linebreak/>
- <emoji name="seven" unicode="&amp;#x0037;&amp;#x20e3;"/> <emoji name="seven" unicode="&amp;#x0037;&amp;#x20e3;"/> from "seven"<linebreak/>
+ <emoji name="service_dog" unicode="&amp;#x1f415;&amp;#x200d;&amp;#x1f9ba;"/> <emoji name="service_dog" unicode="&amp;#x1f415;&amp;#x200d;&amp;#x1f9ba;"/> from "service_dog"<linebreak/>
+ <emoji name="seven" unicode="&amp;#x0037;&amp;#xfe0f;&amp;#x20e3;"/> <emoji name="seven" unicode="&amp;#x0037;&amp;#xfe0f;&amp;#x20e3;"/> from "seven"<linebreak/>
+ <emoji name="sewing_needle" unicode="&amp;#x1faa1;"/> <emoji name="sewing_needle" unicode="&amp;#x1faa1;"/> from "sewing_needle"<linebreak/>
  <emoji name="seychelles" unicode="&amp;#x1f1f8;&amp;#x1f1e8;"/> <emoji name="seychelles" unicode="&amp;#x1f1f8;&amp;#x1f1e8;"/> from "seychelles"<linebreak/>
  <emoji name="shallow_pan_of_food" unicode="&amp;#x1f958;"/> <emoji name="shallow_pan_of_food" unicode="&amp;#x1f958;"/> from "shallow_pan_of_food"<linebreak/>
  <emoji name="shamrock" unicode="&amp;#x2618;"/> <emoji name="shamrock" unicode="&amp;#x2618;"/> from "shamrock"<linebreak/>
  <emoji name="shoe" unicode="&amp;#x1f45e;"/> <emoji name="shoe" unicode="&amp;#x1f45e;"/> from "shoe"<linebreak/>
  <emoji name="shopping" unicode="&amp;#x1f6cd;"/> <emoji name="shopping" unicode="&amp;#x1f6cd;"/> from "shopping"<linebreak/>
  <emoji name="shopping_cart" unicode="&amp;#x1f6d2;"/> <emoji name="shopping_cart" unicode="&amp;#x1f6d2;"/> from "shopping_cart"<linebreak/>
+ <emoji name="shorts" unicode="&amp;#x1fa73;"/> <emoji name="shorts" unicode="&amp;#x1fa73;"/> from "shorts"<linebreak/>
  <emoji name="shower" unicode="&amp;#x1f6bf;"/> <emoji name="shower" unicode="&amp;#x1f6bf;"/> from "shower"<linebreak/>
  <emoji name="shrimp" unicode="&amp;#x1f990;"/> <emoji name="shrimp" unicode="&amp;#x1f990;"/> from "shrimp"<linebreak/>
+ <emoji name="shrug" unicode="&amp;#x1f937;"/> <emoji name="shrug" unicode="&amp;#x1f937;"/> from "shrug"<linebreak/>
+ <emoji name="shushing_face" unicode="&amp;#x1f92b;"/> <emoji name="shushing_face" unicode="&amp;#x1f92b;"/> from "shushing_face"<linebreak/>
  <emoji name="sierra_leone" unicode="&amp;#x1f1f8;&amp;#x1f1f1;"/> <emoji name="sierra_leone" unicode="&amp;#x1f1f8;&amp;#x1f1f1;"/> from "sierra_leone"<linebreak/>
  <emoji name="signal_strength" unicode="&amp;#x1f4f6;"/> <emoji name="signal_strength" unicode="&amp;#x1f4f6;"/> from "signal_strength"<linebreak/>
  <emoji name="singapore" unicode="&amp;#x1f1f8;&amp;#x1f1ec;"/> <emoji name="singapore" unicode="&amp;#x1f1f8;&amp;#x1f1ec;"/> from "singapore"<linebreak/>
+ <emoji name="singer" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f3a4;"/> <emoji name="singer" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f3a4;"/> from "singer"<linebreak/>
  <emoji name="sint_maarten" unicode="&amp;#x1f1f8;&amp;#x1f1fd;"/> <emoji name="sint_maarten" unicode="&amp;#x1f1f8;&amp;#x1f1fd;"/> from "sint_maarten"<linebreak/>
- <emoji name="six" unicode="&amp;#x0036;&amp;#x20e3;"/> <emoji name="six" unicode="&amp;#x0036;&amp;#x20e3;"/> from "six"<linebreak/>
+ <emoji name="six" unicode="&amp;#x0036;&amp;#xfe0f;&amp;#x20e3;"/> <emoji name="six" unicode="&amp;#x0036;&amp;#xfe0f;&amp;#x20e3;"/> from "six"<linebreak/>
  <emoji name="six_pointed_star" unicode="&amp;#x1f52f;"/> <emoji name="six_pointed_star" unicode="&amp;#x1f52f;"/> from "six_pointed_star"<linebreak/>
+ <emoji name="skateboard" unicode="&amp;#x1f6f9;"/> <emoji name="skateboard" unicode="&amp;#x1f6f9;"/> from "skateboard"<linebreak/>
  <emoji name="ski" unicode="&amp;#x1f3bf;"/> <emoji name="ski" unicode="&amp;#x1f3bf;"/> from "ski"<linebreak/>
  <emoji name="skier" unicode="&amp;#x26f7;"/> <emoji name="skier" unicode="&amp;#x26f7;"/> from "skier"<linebreak/>
  <emoji name="skull" unicode="&amp;#x1f480;"/> <emoji name="skull" unicode="&amp;#x1f480;"/> from "skull"<linebreak/>
  <emoji name="skull_and_crossbones" unicode="&amp;#x2620;"/> <emoji name="skull_and_crossbones" unicode="&amp;#x2620;"/> from "skull_and_crossbones"<linebreak/>
+ <emoji name="skunk" unicode="&amp;#x1f9a8;"/> <emoji name="skunk" unicode="&amp;#x1f9a8;"/> from "skunk"<linebreak/>
+ <emoji name="sled" unicode="&amp;#x1f6f7;"/> <emoji name="sled" unicode="&amp;#x1f6f7;"/> from "sled"<linebreak/>
  <emoji name="sleeping" unicode="&amp;#x1f634;"/> <emoji name="sleeping" unicode="&amp;#x1f634;"/> from "sleeping"<linebreak/>
  <emoji name="sleeping_bed" unicode="&amp;#x1f6cc;"/> <emoji name="sleeping_bed" unicode="&amp;#x1f6cc;"/> from "sleeping_bed"<linebreak/>
  <emoji name="sleepy" unicode="&amp;#x1f62a;"/> <emoji name="sleepy" unicode="&amp;#x1f62a;"/> from "sleepy"<linebreak/>
  <emoji name="slightly_frowning_face" unicode="&amp;#x1f641;"/> <emoji name="slightly_frowning_face" unicode="&amp;#x1f641;"/> from "slightly_frowning_face"<linebreak/>
  <emoji name="slightly_smiling_face" unicode="&amp;#x1f642;"/> <emoji name="slightly_smiling_face" unicode="&amp;#x1f642;"/> from "slightly_smiling_face"<linebreak/>
  <emoji name="slot_machine" unicode="&amp;#x1f3b0;"/> <emoji name="slot_machine" unicode="&amp;#x1f3b0;"/> from "slot_machine"<linebreak/>
+ <emoji name="sloth" unicode="&amp;#x1f9a5;"/> <emoji name="sloth" unicode="&amp;#x1f9a5;"/> from "sloth"<linebreak/>
  <emoji name="slovakia" unicode="&amp;#x1f1f8;&amp;#x1f1f0;"/> <emoji name="slovakia" unicode="&amp;#x1f1f8;&amp;#x1f1f0;"/> from "slovakia"<linebreak/>
  <emoji name="slovenia" unicode="&amp;#x1f1f8;&amp;#x1f1ee;"/> <emoji name="slovenia" unicode="&amp;#x1f1f8;&amp;#x1f1ee;"/> from "slovenia"<linebreak/>
  <emoji name="small_airplane" unicode="&amp;#x1f6e9;"/> <emoji name="small_airplane" unicode="&amp;#x1f6e9;"/> from "small_airplane"<linebreak/>
  <emoji name="smile_cat" unicode="&amp;#x1f638;"/> <emoji name="smile_cat" unicode="&amp;#x1f638;"/> from "smile_cat"<linebreak/>
  <emoji name="smiley" unicode="&amp;#x1f603;"/> <emoji name="smiley" unicode="&amp;#x1f603;"/> from "smiley"<linebreak/>
  <emoji name="smiley_cat" unicode="&amp;#x1f63a;"/> <emoji name="smiley_cat" unicode="&amp;#x1f63a;"/> from "smiley_cat"<linebreak/>
+ <emoji name="smiling_face_with_tear" unicode="&amp;#x1f972;"/> <emoji name="smiling_face_with_tear" unicode="&amp;#x1f972;"/> from "smiling_face_with_tear"<linebreak/>
+ <emoji name="smiling_face_with_three_hearts" unicode="&amp;#x1f970;"/> <emoji name="smiling_face_with_three_hearts" unicode="&amp;#x1f970;"/> from "smiling_face_with_three_hearts"<linebreak/>
  <emoji name="smiling_imp" unicode="&amp;#x1f608;"/> <emoji name="smiling_imp" unicode="&amp;#x1f608;"/> from "smiling_imp"<linebreak/>
  <emoji name="smirk" unicode="&amp;#x1f60f;"/> <emoji name="smirk" unicode="&amp;#x1f60f;"/> from "smirk"<linebreak/>
  <emoji name="smirk_cat" unicode="&amp;#x1f63c;"/> <emoji name="smirk_cat" unicode="&amp;#x1f63c;"/> from "smirk_cat"<linebreak/>
  <emoji name="snowflake" unicode="&amp;#x2744;"/> <emoji name="snowflake" unicode="&amp;#x2744;"/> from "snowflake"<linebreak/>
  <emoji name="snowman" unicode="&amp;#x26c4;"/> <emoji name="snowman" unicode="&amp;#x26c4;"/> from "snowman"<linebreak/>
  <emoji name="snowman_with_snow" unicode="&amp;#x2603;"/> <emoji name="snowman_with_snow" unicode="&amp;#x2603;"/> from "snowman_with_snow"<linebreak/>
+ <emoji name="soap" unicode="&amp;#x1f9fc;"/> <emoji name="soap" unicode="&amp;#x1f9fc;"/> from "soap"<linebreak/>
  <emoji name="sob" unicode="&amp;#x1f62d;"/> <emoji name="sob" unicode="&amp;#x1f62d;"/> from "sob"<linebreak/>
  <emoji name="soccer" unicode="&amp;#x26bd;"/> <emoji name="soccer" unicode="&amp;#x26bd;"/> from "soccer"<linebreak/>
+ <emoji name="socks" unicode="&amp;#x1f9e6;"/> <emoji name="socks" unicode="&amp;#x1f9e6;"/> from "socks"<linebreak/>
+ <emoji name="softball" unicode="&amp;#x1f94e;"/> <emoji name="softball" unicode="&amp;#x1f94e;"/> from "softball"<linebreak/>
  <emoji name="solomon_islands" unicode="&amp;#x1f1f8;&amp;#x1f1e7;"/> <emoji name="solomon_islands" unicode="&amp;#x1f1f8;&amp;#x1f1e7;"/> from "solomon_islands"<linebreak/>
  <emoji name="somalia" unicode="&amp;#x1f1f8;&amp;#x1f1f4;"/> <emoji name="somalia" unicode="&amp;#x1f1f8;&amp;#x1f1f4;"/> from "somalia"<linebreak/>
  <emoji name="soon" unicode="&amp;#x1f51c;"/> <emoji name="soon" unicode="&amp;#x1f51c;"/> from "soon"<linebreak/>
  <emoji name="spider_web" unicode="&amp;#x1f578;"/> <emoji name="spider_web" unicode="&amp;#x1f578;"/> from "spider_web"<linebreak/>
  <emoji name="spiral_calendar" unicode="&amp;#x1f5d3;"/> <emoji name="spiral_calendar" unicode="&amp;#x1f5d3;"/> from "spiral_calendar"<linebreak/>
  <emoji name="spiral_notepad" unicode="&amp;#x1f5d2;"/> <emoji name="spiral_notepad" unicode="&amp;#x1f5d2;"/> from "spiral_notepad"<linebreak/>
+ <emoji name="sponge" unicode="&amp;#x1f9fd;"/> <emoji name="sponge" unicode="&amp;#x1f9fd;"/> from "sponge"<linebreak/>
  <emoji name="spoon" unicode="&amp;#x1f944;"/> <emoji name="spoon" unicode="&amp;#x1f944;"/> from "spoon"<linebreak/>
  <emoji name="squid" unicode="&amp;#x1f991;"/> <emoji name="squid" unicode="&amp;#x1f991;"/> from "squid"<linebreak/>
  <emoji name="sri_lanka" unicode="&amp;#x1f1f1;&amp;#x1f1f0;"/> <emoji name="sri_lanka" unicode="&amp;#x1f1f1;&amp;#x1f1f0;"/> from "sri_lanka"<linebreak/>
  <emoji name="st_helena" unicode="&amp;#x1f1f8;&amp;#x1f1ed;"/> <emoji name="st_helena" unicode="&amp;#x1f1f8;&amp;#x1f1ed;"/> from "st_helena"<linebreak/>
  <emoji name="st_kitts_nevis" unicode="&amp;#x1f1f0;&amp;#x1f1f3;"/> <emoji name="st_kitts_nevis" unicode="&amp;#x1f1f0;&amp;#x1f1f3;"/> from "st_kitts_nevis"<linebreak/>
  <emoji name="st_lucia" unicode="&amp;#x1f1f1;&amp;#x1f1e8;"/> <emoji name="st_lucia" unicode="&amp;#x1f1f1;&amp;#x1f1e8;"/> from "st_lucia"<linebreak/>
+ <emoji name="st_martin" unicode="&amp;#x1f1f2;&amp;#x1f1eb;"/> <emoji name="st_martin" unicode="&amp;#x1f1f2;&amp;#x1f1eb;"/> from "st_martin"<linebreak/>
  <emoji name="st_pierre_miquelon" unicode="&amp;#x1f1f5;&amp;#x1f1f2;"/> <emoji name="st_pierre_miquelon" unicode="&amp;#x1f1f5;&amp;#x1f1f2;"/> from "st_pierre_miquelon"<linebreak/>
  <emoji name="st_vincent_grenadines" unicode="&amp;#x1f1fb;&amp;#x1f1e8;"/> <emoji name="st_vincent_grenadines" unicode="&amp;#x1f1fb;&amp;#x1f1e8;"/> from "st_vincent_grenadines"<linebreak/>
  <emoji name="stadium" unicode="&amp;#x1f3df;"/> <emoji name="stadium" unicode="&amp;#x1f3df;"/> from "stadium"<linebreak/>
+ <emoji name="standing_man" unicode="&amp;#x1f9cd;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="standing_man" unicode="&amp;#x1f9cd;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "standing_man"<linebreak/>
+ <emoji name="standing_person" unicode="&amp;#x1f9cd;"/> <emoji name="standing_person" unicode="&amp;#x1f9cd;"/> from "standing_person"<linebreak/>
+ <emoji name="standing_woman" unicode="&amp;#x1f9cd;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="standing_woman" unicode="&amp;#x1f9cd;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "standing_woman"<linebreak/>
  <emoji name="star" unicode="&amp;#x2b50;"/> <emoji name="star" unicode="&amp;#x2b50;"/> from "star"<linebreak/>
  <emoji name="star2" unicode="&amp;#x1f31f;"/> <emoji name="star2" unicode="&amp;#x1f31f;"/> from "star2"<linebreak/>
  <emoji name="star_and_crescent" unicode="&amp;#x262a;"/> <emoji name="star_and_crescent" unicode="&amp;#x262a;"/> from "star_and_crescent"<linebreak/>
  <emoji name="star_of_david" unicode="&amp;#x2721;"/> <emoji name="star_of_david" unicode="&amp;#x2721;"/> from "star_of_david"<linebreak/>
+ <emoji name="star_struck" unicode="&amp;#x1f929;"/> <emoji name="star_struck" unicode="&amp;#x1f929;"/> from "star_struck"<linebreak/>
  <emoji name="stars" unicode="&amp;#x1f320;"/> <emoji name="stars" unicode="&amp;#x1f320;"/> from "stars"<linebreak/>
  <emoji name="station" unicode="&amp;#x1f689;"/> <emoji name="station" unicode="&amp;#x1f689;"/> from "station"<linebreak/>
  <emoji name="statue_of_liberty" unicode="&amp;#x1f5fd;"/> <emoji name="statue_of_liberty" unicode="&amp;#x1f5fd;"/> from "statue_of_liberty"<linebreak/>
  <emoji name="steam_locomotive" unicode="&amp;#x1f682;"/> <emoji name="steam_locomotive" unicode="&amp;#x1f682;"/> from "steam_locomotive"<linebreak/>
+ <emoji name="stethoscope" unicode="&amp;#x1fa7a;"/> <emoji name="stethoscope" unicode="&amp;#x1fa7a;"/> from "stethoscope"<linebreak/>
  <emoji name="stew" unicode="&amp;#x1f372;"/> <emoji name="stew" unicode="&amp;#x1f372;"/> from "stew"<linebreak/>
  <emoji name="stop_button" unicode="&amp;#x23f9;"/> <emoji name="stop_button" unicode="&amp;#x23f9;"/> from "stop_button"<linebreak/>
  <emoji name="stop_sign" unicode="&amp;#x1f6d1;"/> <emoji name="stop_sign" unicode="&amp;#x1f6d1;"/> from "stop_sign"<linebreak/>
  <emoji name="stuck_out_tongue" unicode="&amp;#x1f61b;"/> <emoji name="stuck_out_tongue" unicode="&amp;#x1f61b;"/> from "stuck_out_tongue"<linebreak/>
  <emoji name="stuck_out_tongue_closed_eyes" unicode="&amp;#x1f61d;"/> <emoji name="stuck_out_tongue_closed_eyes" unicode="&amp;#x1f61d;"/> from "stuck_out_tongue_closed_eyes"<linebreak/>
  <emoji name="stuck_out_tongue_winking_eye" unicode="&amp;#x1f61c;"/> <emoji name="stuck_out_tongue_winking_eye" unicode="&amp;#x1f61c;"/> from "stuck_out_tongue_winking_eye"<linebreak/>
+ <emoji name="student" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f393;"/> <emoji name="student" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f393;"/> from "student"<linebreak/>
  <emoji name="studio_microphone" unicode="&amp;#x1f399;"/> <emoji name="studio_microphone" unicode="&amp;#x1f399;"/> from "studio_microphone"<linebreak/>
  <emoji name="stuffed_flatbread" unicode="&amp;#x1f959;"/> <emoji name="stuffed_flatbread" unicode="&amp;#x1f959;"/> from "stuffed_flatbread"<linebreak/>
  <emoji name="sudan" unicode="&amp;#x1f1f8;&amp;#x1f1e9;"/> <emoji name="sudan" unicode="&amp;#x1f1f8;&amp;#x1f1e9;"/> from "sudan"<linebreak/>
  <emoji name="sunny" unicode="&amp;#x2600;"/> <emoji name="sunny" unicode="&amp;#x2600;"/> from "sunny"<linebreak/>
  <emoji name="sunrise" unicode="&amp;#x1f305;"/> <emoji name="sunrise" unicode="&amp;#x1f305;"/> from "sunrise"<linebreak/>
  <emoji name="sunrise_over_mountains" unicode="&amp;#x1f304;"/> <emoji name="sunrise_over_mountains" unicode="&amp;#x1f304;"/> from "sunrise_over_mountains"<linebreak/>
+ <emoji name="superhero" unicode="&amp;#x1f9b8;"/> <emoji name="superhero" unicode="&amp;#x1f9b8;"/> from "superhero"<linebreak/>
+ <emoji name="superhero_man" unicode="&amp;#x1f9b8;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="superhero_man" unicode="&amp;#x1f9b8;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "superhero_man"<linebreak/>
+ <emoji name="superhero_woman" unicode="&amp;#x1f9b8;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="superhero_woman" unicode="&amp;#x1f9b8;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "superhero_woman"<linebreak/>
+ <emoji name="supervillain" unicode="&amp;#x1f9b9;"/> <emoji name="supervillain" unicode="&amp;#x1f9b9;"/> from "supervillain"<linebreak/>
+ <emoji name="supervillain_man" unicode="&amp;#x1f9b9;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="supervillain_man" unicode="&amp;#x1f9b9;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "supervillain_man"<linebreak/>
+ <emoji name="supervillain_woman" unicode="&amp;#x1f9b9;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="supervillain_woman" unicode="&amp;#x1f9b9;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "supervillain_woman"<linebreak/>
  <emoji name="surfer" unicode="&amp;#x1f3c4;"/> <emoji name="surfer" unicode="&amp;#x1f3c4;"/> from "surfer"<linebreak/>
- <emoji name="surfing_man" unicode="&amp;#x1f3c4;"/> <emoji name="surfing_man" unicode="&amp;#x1f3c4;"/> from "surfing_man"<linebreak/>
- <emoji name="surfing_woman" unicode="&amp;#x1f3c4;&amp;#x2640;"/> <emoji name="surfing_woman" unicode="&amp;#x1f3c4;&amp;#x2640;"/> from "surfing_woman"<linebreak/>
+ <emoji name="surfing_man" unicode="&amp;#x1f3c4;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="surfing_man" unicode="&amp;#x1f3c4;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "surfing_man"<linebreak/>
+ <emoji name="surfing_woman" unicode="&amp;#x1f3c4;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="surfing_woman" unicode="&amp;#x1f3c4;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "surfing_woman"<linebreak/>
  <emoji name="suriname" unicode="&amp;#x1f1f8;&amp;#x1f1f7;"/> <emoji name="suriname" unicode="&amp;#x1f1f8;&amp;#x1f1f7;"/> from "suriname"<linebreak/>
  <emoji name="sushi" unicode="&amp;#x1f363;"/> <emoji name="sushi" unicode="&amp;#x1f363;"/> from "sushi"<linebreak/>
  <emoji name="suspension_railway" unicode="&amp;#x1f69f;"/> <emoji name="suspension_railway" unicode="&amp;#x1f69f;"/> from "suspension_railway"<linebreak/>
+ <emoji name="svalbard_jan_mayen" unicode="&amp;#x1f1f8;&amp;#x1f1ef;"/> <emoji name="svalbard_jan_mayen" unicode="&amp;#x1f1f8;&amp;#x1f1ef;"/> from "svalbard_jan_mayen"<linebreak/>
+ <emoji name="swan" unicode="&amp;#x1f9a2;"/> <emoji name="swan" unicode="&amp;#x1f9a2;"/> from "swan"<linebreak/>
  <emoji name="swaziland" unicode="&amp;#x1f1f8;&amp;#x1f1ff;"/> <emoji name="swaziland" unicode="&amp;#x1f1f8;&amp;#x1f1ff;"/> from "swaziland"<linebreak/>
  <emoji name="sweat" unicode="&amp;#x1f613;"/> <emoji name="sweat" unicode="&amp;#x1f613;"/> from "sweat"<linebreak/>
  <emoji name="sweat_drops" unicode="&amp;#x1f4a6;"/> <emoji name="sweat_drops" unicode="&amp;#x1f4a6;"/> from "sweat_drops"<linebreak/>
  <emoji name="sweat_smile" unicode="&amp;#x1f605;"/> <emoji name="sweat_smile" unicode="&amp;#x1f605;"/> from "sweat_smile"<linebreak/>
  <emoji name="sweden" unicode="&amp;#x1f1f8;&amp;#x1f1ea;"/> <emoji name="sweden" unicode="&amp;#x1f1f8;&amp;#x1f1ea;"/> from "sweden"<linebreak/>
  <emoji name="sweet_potato" unicode="&amp;#x1f360;"/> <emoji name="sweet_potato" unicode="&amp;#x1f360;"/> from "sweet_potato"<linebreak/>
+ <emoji name="swim_brief" unicode="&amp;#x1fa72;"/> <emoji name="swim_brief" unicode="&amp;#x1fa72;"/> from "swim_brief"<linebreak/>
  <emoji name="swimmer" unicode="&amp;#x1f3ca;"/> <emoji name="swimmer" unicode="&amp;#x1f3ca;"/> from "swimmer"<linebreak/>
- <emoji name="swimming_man" unicode="&amp;#x1f3ca;"/> <emoji name="swimming_man" unicode="&amp;#x1f3ca;"/> from "swimming_man"<linebreak/>
- <emoji name="swimming_woman" unicode="&amp;#x1f3ca;&amp;#x2640;"/> <emoji name="swimming_woman" unicode="&amp;#x1f3ca;&amp;#x2640;"/> from "swimming_woman"<linebreak/>
+ <emoji name="swimming_man" unicode="&amp;#x1f3ca;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="swimming_man" unicode="&amp;#x1f3ca;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "swimming_man"<linebreak/>
+ <emoji name="swimming_woman" unicode="&amp;#x1f3ca;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="swimming_woman" unicode="&amp;#x1f3ca;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "swimming_woman"<linebreak/>
  <emoji name="switzerland" unicode="&amp;#x1f1e8;&amp;#x1f1ed;"/> <emoji name="switzerland" unicode="&amp;#x1f1e8;&amp;#x1f1ed;"/> from "switzerland"<linebreak/>
  <emoji name="symbols" unicode="&amp;#x1f523;"/> <emoji name="symbols" unicode="&amp;#x1f523;"/> from "symbols"<linebreak/>
  <emoji name="synagogue" unicode="&amp;#x1f54d;"/> <emoji name="synagogue" unicode="&amp;#x1f54d;"/> from "synagogue"<linebreak/>
  <emoji name="syria" unicode="&amp;#x1f1f8;&amp;#x1f1fe;"/> <emoji name="syria" unicode="&amp;#x1f1f8;&amp;#x1f1fe;"/> from "syria"<linebreak/>
  <emoji name="syringe" unicode="&amp;#x1f489;"/> <emoji name="syringe" unicode="&amp;#x1f489;"/> from "syringe"<linebreak/>
+ <emoji name="t-rex" unicode="&amp;#x1f996;"/> <emoji name="t-rex" unicode="&amp;#x1f996;"/> from "t-rex"<linebreak/>
  <emoji name="taco" unicode="&amp;#x1f32e;"/> <emoji name="taco" unicode="&amp;#x1f32e;"/> from "taco"<linebreak/>
  <emoji name="tada" unicode="&amp;#x1f389;"/> <emoji name="tada" unicode="&amp;#x1f389;"/> from "tada"<linebreak/>
  <emoji name="taiwan" unicode="&amp;#x1f1f9;&amp;#x1f1fc;"/> <emoji name="taiwan" unicode="&amp;#x1f1f9;&amp;#x1f1fc;"/> from "taiwan"<linebreak/>
  <emoji name="tajikistan" unicode="&amp;#x1f1f9;&amp;#x1f1ef;"/> <emoji name="tajikistan" unicode="&amp;#x1f1f9;&amp;#x1f1ef;"/> from "tajikistan"<linebreak/>
+ <emoji name="takeout_box" unicode="&amp;#x1f961;"/> <emoji name="takeout_box" unicode="&amp;#x1f961;"/> from "takeout_box"<linebreak/>
+ <emoji name="tamale" unicode="&amp;#x1fad4;"/> <emoji name="tamale" unicode="&amp;#x1fad4;"/> from "tamale"<linebreak/>
  <emoji name="tanabata_tree" unicode="&amp;#x1f38b;"/> <emoji name="tanabata_tree" unicode="&amp;#x1f38b;"/> from "tanabata_tree"<linebreak/>
  <emoji name="tangerine" unicode="&amp;#x1f34a;"/> <emoji name="tangerine" unicode="&amp;#x1f34a;"/> from "tangerine"<linebreak/>
  <emoji name="tanzania" unicode="&amp;#x1f1f9;&amp;#x1f1ff;"/> <emoji name="tanzania" unicode="&amp;#x1f1f9;&amp;#x1f1ff;"/> from "tanzania"<linebreak/>
  <emoji name="taurus" unicode="&amp;#x2649;"/> <emoji name="taurus" unicode="&amp;#x2649;"/> from "taurus"<linebreak/>
  <emoji name="taxi" unicode="&amp;#x1f695;"/> <emoji name="taxi" unicode="&amp;#x1f695;"/> from "taxi"<linebreak/>
  <emoji name="tea" unicode="&amp;#x1f375;"/> <emoji name="tea" unicode="&amp;#x1f375;"/> from "tea"<linebreak/>
+ <emoji name="teacher" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f3eb;"/> <emoji name="teacher" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f3eb;"/> from "teacher"<linebreak/>
+ <emoji name="teapot" unicode="&amp;#x1fad6;"/> <emoji name="teapot" unicode="&amp;#x1fad6;"/> from "teapot"<linebreak/>
+ <emoji name="technologist" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f4bb;"/> <emoji name="technologist" unicode="&amp;#x1f9d1;&amp;#x200d;&amp;#x1f4bb;"/> from "technologist"<linebreak/>
+ <emoji name="teddy_bear" unicode="&amp;#x1f9f8;"/> <emoji name="teddy_bear" unicode="&amp;#x1f9f8;"/> from "teddy_bear"<linebreak/>
  <emoji name="telephone" unicode="&amp;#x260e;"/> <emoji name="telephone" unicode="&amp;#x260e;"/> from "telephone"<linebreak/>
  <emoji name="telephone_receiver" unicode="&amp;#x1f4de;"/> <emoji name="telephone_receiver" unicode="&amp;#x1f4de;"/> from "telephone_receiver"<linebreak/>
  <emoji name="telescope" unicode="&amp;#x1f52d;"/> <emoji name="telescope" unicode="&amp;#x1f52d;"/> from "telescope"<linebreak/>
  <emoji name="tennis" unicode="&amp;#x1f3be;"/> <emoji name="tennis" unicode="&amp;#x1f3be;"/> from "tennis"<linebreak/>
  <emoji name="tent" unicode="&amp;#x26fa;"/> <emoji name="tent" unicode="&amp;#x26fa;"/> from "tent"<linebreak/>
+ <emoji name="test_tube" unicode="&amp;#x1f9ea;"/> <emoji name="test_tube" unicode="&amp;#x1f9ea;"/> from "test_tube"<linebreak/>
  <emoji name="thailand" unicode="&amp;#x1f1f9;&amp;#x1f1ed;"/> <emoji name="thailand" unicode="&amp;#x1f1f9;&amp;#x1f1ed;"/> from "thailand"<linebreak/>
  <emoji name="thermometer" unicode="&amp;#x1f321;"/> <emoji name="thermometer" unicode="&amp;#x1f321;"/> from "thermometer"<linebreak/>
  <emoji name="thinking" unicode="&amp;#x1f914;"/> <emoji name="thinking" unicode="&amp;#x1f914;"/> from "thinking"<linebreak/>
+ <emoji name="thong_sandal" unicode="&amp;#x1fa74;"/> <emoji name="thong_sandal" unicode="&amp;#x1fa74;"/> from "thong_sandal"<linebreak/>
  <emoji name="thought_balloon" unicode="&amp;#x1f4ad;"/> <emoji name="thought_balloon" unicode="&amp;#x1f4ad;"/> from "thought_balloon"<linebreak/>
- <emoji name="three" unicode="&amp;#x0033;&amp;#x20e3;"/> <emoji name="three" unicode="&amp;#x0033;&amp;#x20e3;"/> from "three"<linebreak/>
+ <emoji name="thread" unicode="&amp;#x1f9f5;"/> <emoji name="thread" unicode="&amp;#x1f9f5;"/> from "thread"<linebreak/>
+ <emoji name="three" unicode="&amp;#x0033;&amp;#xfe0f;&amp;#x20e3;"/> <emoji name="three" unicode="&amp;#x0033;&amp;#xfe0f;&amp;#x20e3;"/> from "three"<linebreak/>
  <emoji name="thumbsdown" unicode="&amp;#x1f44e;"/> <emoji name="thumbsdown" unicode="&amp;#x1f44e;"/> from "thumbsdown"<linebreak/>
  <emoji name="thumbsup" unicode="&amp;#x1f44d;"/> <emoji name="thumbsup" unicode="&amp;#x1f44d;"/> from "thumbsup"<linebreak/>
  <emoji name="ticket" unicode="&amp;#x1f3ab;"/> <emoji name="ticket" unicode="&amp;#x1f3ab;"/> from "ticket"<linebreak/>
  <emoji name="tiger2" unicode="&amp;#x1f405;"/> <emoji name="tiger2" unicode="&amp;#x1f405;"/> from "tiger2"<linebreak/>
  <emoji name="timer_clock" unicode="&amp;#x23f2;"/> <emoji name="timer_clock" unicode="&amp;#x23f2;"/> from "timer_clock"<linebreak/>
  <emoji name="timor_leste" unicode="&amp;#x1f1f9;&amp;#x1f1f1;"/> <emoji name="timor_leste" unicode="&amp;#x1f1f9;&amp;#x1f1f1;"/> from "timor_leste"<linebreak/>
- <emoji name="tipping_hand_man" unicode="&amp;#x1f481;&amp;#x2642;"/> <emoji name="tipping_hand_man" unicode="&amp;#x1f481;&amp;#x2642;"/> from "tipping_hand_man"<linebreak/>
- <emoji name="tipping_hand_woman" unicode="&amp;#x1f481;"/> <emoji name="tipping_hand_woman" unicode="&amp;#x1f481;"/> from "tipping_hand_woman"<linebreak/>
+ <emoji name="tipping_hand_man" unicode="&amp;#x1f481;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="tipping_hand_man" unicode="&amp;#x1f481;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "tipping_hand_man"<linebreak/>
+ <emoji name="tipping_hand_person" unicode="&amp;#x1f481;"/> <emoji name="tipping_hand_person" unicode="&amp;#x1f481;"/> from "tipping_hand_person"<linebreak/>
+ <emoji name="tipping_hand_woman" unicode="&amp;#x1f481;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="tipping_hand_woman" unicode="&amp;#x1f481;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "tipping_hand_woman"<linebreak/>
  <emoji name="tired_face" unicode="&amp;#x1f62b;"/> <emoji name="tired_face" unicode="&amp;#x1f62b;"/> from "tired_face"<linebreak/>
  <emoji name="tm" unicode="&amp;#x2122;"/> <emoji name="tm" unicode="&amp;#x2122;"/> from "tm"<linebreak/>
  <emoji name="togo" unicode="&amp;#x1f1f9;&amp;#x1f1ec;"/> <emoji name="togo" unicode="&amp;#x1f1f9;&amp;#x1f1ec;"/> from "togo"<linebreak/>
  <emoji name="tomato" unicode="&amp;#x1f345;"/> <emoji name="tomato" unicode="&amp;#x1f345;"/> from "tomato"<linebreak/>
  <emoji name="tonga" unicode="&amp;#x1f1f9;&amp;#x1f1f4;"/> <emoji name="tonga" unicode="&amp;#x1f1f9;&amp;#x1f1f4;"/> from "tonga"<linebreak/>
  <emoji name="tongue" unicode="&amp;#x1f445;"/> <emoji name="tongue" unicode="&amp;#x1f445;"/> from "tongue"<linebreak/>
+ <emoji name="toolbox" unicode="&amp;#x1f9f0;"/> <emoji name="toolbox" unicode="&amp;#x1f9f0;"/> from "toolbox"<linebreak/>
+ <emoji name="tooth" unicode="&amp;#x1f9b7;"/> <emoji name="tooth" unicode="&amp;#x1f9b7;"/> from "tooth"<linebreak/>
+ <emoji name="toothbrush" unicode="&amp;#x1faa5;"/> <emoji name="toothbrush" unicode="&amp;#x1faa5;"/> from "toothbrush"<linebreak/>
  <emoji name="top" unicode="&amp;#x1f51d;"/> <emoji name="top" unicode="&amp;#x1f51d;"/> from "top"<linebreak/>
  <emoji name="tophat" unicode="&amp;#x1f3a9;"/> <emoji name="tophat" unicode="&amp;#x1f3a9;"/> from "tophat"<linebreak/>
  <emoji name="tornado" unicode="&amp;#x1f32a;"/> <emoji name="tornado" unicode="&amp;#x1f32a;"/> from "tornado"<linebreak/>
  <emoji name="train" unicode="&amp;#x1f68b;"/> <emoji name="train" unicode="&amp;#x1f68b;"/> from "train"<linebreak/>
  <emoji name="train2" unicode="&amp;#x1f686;"/> <emoji name="train2" unicode="&amp;#x1f686;"/> from "train2"<linebreak/>
  <emoji name="tram" unicode="&amp;#x1f68a;"/> <emoji name="tram" unicode="&amp;#x1f68a;"/> from "tram"<linebreak/>
+ <emoji name="transgender_flag" unicode="&amp;#x1f3f3;&amp;#xfe0f;&amp;#x200d;&amp;#x26a7;&amp;#xfe0f;"/> <emoji name="transgender_flag" unicode="&amp;#x1f3f3;&amp;#xfe0f;&amp;#x200d;&amp;#x26a7;&amp;#xfe0f;"/> from "transgender_flag"<linebreak/>
+ <emoji name="transgender_symbol" unicode="&amp;#x26a7;"/> <emoji name="transgender_symbol" unicode="&amp;#x26a7;"/> from "transgender_symbol"<linebreak/>
  <emoji name="triangular_flag_on_post" unicode="&amp;#x1f6a9;"/> <emoji name="triangular_flag_on_post" unicode="&amp;#x1f6a9;"/> from "triangular_flag_on_post"<linebreak/>
  <emoji name="triangular_ruler" unicode="&amp;#x1f4d0;"/> <emoji name="triangular_ruler" unicode="&amp;#x1f4d0;"/> from "triangular_ruler"<linebreak/>
  <emoji name="trident" unicode="&amp;#x1f531;"/> <emoji name="trident" unicode="&amp;#x1f531;"/> from "trident"<linebreak/>
  <emoji name="trinidad_tobago" unicode="&amp;#x1f1f9;&amp;#x1f1f9;"/> <emoji name="trinidad_tobago" unicode="&amp;#x1f1f9;&amp;#x1f1f9;"/> from "trinidad_tobago"<linebreak/>
+ <emoji name="tristan_da_cunha" unicode="&amp;#x1f1f9;&amp;#x1f1e6;"/> <emoji name="tristan_da_cunha" unicode="&amp;#x1f1f9;&amp;#x1f1e6;"/> from "tristan_da_cunha"<linebreak/>
  <emoji name="triumph" unicode="&amp;#x1f624;"/> <emoji name="triumph" unicode="&amp;#x1f624;"/> from "triumph"<linebreak/>
  <emoji name="trolleybus" unicode="&amp;#x1f68e;"/> <emoji name="trolleybus" unicode="&amp;#x1f68e;"/> from "trolleybus"<linebreak/>
  <emoji name="trophy" unicode="&amp;#x1f3c6;"/> <emoji name="trophy" unicode="&amp;#x1f3c6;"/> from "trophy"<linebreak/>
  <emoji name="tuvalu" unicode="&amp;#x1f1f9;&amp;#x1f1fb;"/> <emoji name="tuvalu" unicode="&amp;#x1f1f9;&amp;#x1f1fb;"/> from "tuvalu"<linebreak/>
  <emoji name="tv" unicode="&amp;#x1f4fa;"/> <emoji name="tv" unicode="&amp;#x1f4fa;"/> from "tv"<linebreak/>
  <emoji name="twisted_rightwards_arrows" unicode="&amp;#x1f500;"/> <emoji name="twisted_rightwards_arrows" unicode="&amp;#x1f500;"/> from "twisted_rightwards_arrows"<linebreak/>
- <emoji name="two" unicode="&amp;#x0032;&amp;#x20e3;"/> <emoji name="two" unicode="&amp;#x0032;&amp;#x20e3;"/> from "two"<linebreak/>
+ <emoji name="two" unicode="&amp;#x0032;&amp;#xfe0f;&amp;#x20e3;"/> <emoji name="two" unicode="&amp;#x0032;&amp;#xfe0f;&amp;#x20e3;"/> from "two"<linebreak/>
  <emoji name="two_hearts" unicode="&amp;#x1f495;"/> <emoji name="two_hearts" unicode="&amp;#x1f495;"/> from "two_hearts"<linebreak/>
  <emoji name="two_men_holding_hands" unicode="&amp;#x1f46c;"/> <emoji name="two_men_holding_hands" unicode="&amp;#x1f46c;"/> from "two_men_holding_hands"<linebreak/>
  <emoji name="two_women_holding_hands" unicode="&amp;#x1f46d;"/> <emoji name="two_women_holding_hands" unicode="&amp;#x1f46d;"/> from "two_women_holding_hands"<linebreak/>
  <emoji name="underage" unicode="&amp;#x1f51e;"/> <emoji name="underage" unicode="&amp;#x1f51e;"/> from "underage"<linebreak/>
  <emoji name="unicorn" unicode="&amp;#x1f984;"/> <emoji name="unicorn" unicode="&amp;#x1f984;"/> from "unicorn"<linebreak/>
  <emoji name="united_arab_emirates" unicode="&amp;#x1f1e6;&amp;#x1f1ea;"/> <emoji name="united_arab_emirates" unicode="&amp;#x1f1e6;&amp;#x1f1ea;"/> from "united_arab_emirates"<linebreak/>
+ <emoji name="united_nations" unicode="&amp;#x1f1fa;&amp;#x1f1f3;"/> <emoji name="united_nations" unicode="&amp;#x1f1fa;&amp;#x1f1f3;"/> from "united_nations"<linebreak/>
  <emoji name="unlock" unicode="&amp;#x1f513;"/> <emoji name="unlock" unicode="&amp;#x1f513;"/> from "unlock"<linebreak/>
  <emoji name="up" unicode="&amp;#x1f199;"/> <emoji name="up" unicode="&amp;#x1f199;"/> from "up"<linebreak/>
  <emoji name="upside_down_face" unicode="&amp;#x1f643;"/> <emoji name="upside_down_face" unicode="&amp;#x1f643;"/> from "upside_down_face"<linebreak/>
  <emoji name="uruguay" unicode="&amp;#x1f1fa;&amp;#x1f1fe;"/> <emoji name="uruguay" unicode="&amp;#x1f1fa;&amp;#x1f1fe;"/> from "uruguay"<linebreak/>
  <emoji name="us" unicode="&amp;#x1f1fa;&amp;#x1f1f8;"/> <emoji name="us" unicode="&amp;#x1f1fa;&amp;#x1f1f8;"/> from "us"<linebreak/>
+ <emoji name="us_outlying_islands" unicode="&amp;#x1f1fa;&amp;#x1f1f2;"/> <emoji name="us_outlying_islands" unicode="&amp;#x1f1fa;&amp;#x1f1f2;"/> from "us_outlying_islands"<linebreak/>
  <emoji name="us_virgin_islands" unicode="&amp;#x1f1fb;&amp;#x1f1ee;"/> <emoji name="us_virgin_islands" unicode="&amp;#x1f1fb;&amp;#x1f1ee;"/> from "us_virgin_islands"<linebreak/>
  <emoji name="uzbekistan" unicode="&amp;#x1f1fa;&amp;#x1f1ff;"/> <emoji name="uzbekistan" unicode="&amp;#x1f1fa;&amp;#x1f1ff;"/> from "uzbekistan"<linebreak/>
  <emoji name="v" unicode="&amp;#x270c;"/> <emoji name="v" unicode="&amp;#x270c;"/> from "v"<linebreak/>
+ <emoji name="vampire" unicode="&amp;#x1f9db;"/> <emoji name="vampire" unicode="&amp;#x1f9db;"/> from "vampire"<linebreak/>
+ <emoji name="vampire_man" unicode="&amp;#x1f9db;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="vampire_man" unicode="&amp;#x1f9db;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "vampire_man"<linebreak/>
+ <emoji name="vampire_woman" unicode="&amp;#x1f9db;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="vampire_woman" unicode="&amp;#x1f9db;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "vampire_woman"<linebreak/>
  <emoji name="vanuatu" unicode="&amp;#x1f1fb;&amp;#x1f1fa;"/> <emoji name="vanuatu" unicode="&amp;#x1f1fb;&amp;#x1f1fa;"/> from "vanuatu"<linebreak/>
  <emoji name="vatican_city" unicode="&amp;#x1f1fb;&amp;#x1f1e6;"/> <emoji name="vatican_city" unicode="&amp;#x1f1fb;&amp;#x1f1e6;"/> from "vatican_city"<linebreak/>
  <emoji name="venezuela" unicode="&amp;#x1f1fb;&amp;#x1f1ea;"/> <emoji name="venezuela" unicode="&amp;#x1f1fb;&amp;#x1f1ea;"/> from "venezuela"<linebreak/>
  <emoji name="virgo" unicode="&amp;#x264d;"/> <emoji name="virgo" unicode="&amp;#x264d;"/> from "virgo"<linebreak/>
  <emoji name="volcano" unicode="&amp;#x1f30b;"/> <emoji name="volcano" unicode="&amp;#x1f30b;"/> from "volcano"<linebreak/>
  <emoji name="volleyball" unicode="&amp;#x1f3d0;"/> <emoji name="volleyball" unicode="&amp;#x1f3d0;"/> from "volleyball"<linebreak/>
+ <emoji name="vomiting_face" unicode="&amp;#x1f92e;"/> <emoji name="vomiting_face" unicode="&amp;#x1f92e;"/> from "vomiting_face"<linebreak/>
  <emoji name="vs" unicode="&amp;#x1f19a;"/> <emoji name="vs" unicode="&amp;#x1f19a;"/> from "vs"<linebreak/>
  <emoji name="vulcan_salute" unicode="&amp;#x1f596;"/> <emoji name="vulcan_salute" unicode="&amp;#x1f596;"/> from "vulcan_salute"<linebreak/>
+ <emoji name="waffle" unicode="&amp;#x1f9c7;"/> <emoji name="waffle" unicode="&amp;#x1f9c7;"/> from "waffle"<linebreak/>
+ <emoji name="wales" unicode="&amp;#x1f3f4;&amp;#xe0067;&amp;#xe0062;&amp;#xe0077;&amp;#xe006c;&amp;#xe0073;&amp;#xe007f;"/> <emoji name="wales" unicode="&amp;#x1f3f4;&amp;#xe0067;&amp;#xe0062;&amp;#xe0077;&amp;#xe006c;&amp;#xe0073;&amp;#xe007f;"/> from "wales"<linebreak/>
  <emoji name="walking" unicode="&amp;#x1f6b6;"/> <emoji name="walking" unicode="&amp;#x1f6b6;"/> from "walking"<linebreak/>
- <emoji name="walking_man" unicode="&amp;#x1f6b6;"/> <emoji name="walking_man" unicode="&amp;#x1f6b6;"/> from "walking_man"<linebreak/>
- <emoji name="walking_woman" unicode="&amp;#x1f6b6;&amp;#x2640;"/> <emoji name="walking_woman" unicode="&amp;#x1f6b6;&amp;#x2640;"/> from "walking_woman"<linebreak/>
+ <emoji name="walking_man" unicode="&amp;#x1f6b6;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="walking_man" unicode="&amp;#x1f6b6;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "walking_man"<linebreak/>
+ <emoji name="walking_woman" unicode="&amp;#x1f6b6;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="walking_woman" unicode="&amp;#x1f6b6;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "walking_woman"<linebreak/>
  <emoji name="wallis_futuna" unicode="&amp;#x1f1fc;&amp;#x1f1eb;"/> <emoji name="wallis_futuna" unicode="&amp;#x1f1fc;&amp;#x1f1eb;"/> from "wallis_futuna"<linebreak/>
  <emoji name="waning_crescent_moon" unicode="&amp;#x1f318;"/> <emoji name="waning_crescent_moon" unicode="&amp;#x1f318;"/> from "waning_crescent_moon"<linebreak/>
  <emoji name="waning_gibbous_moon" unicode="&amp;#x1f316;"/> <emoji name="waning_gibbous_moon" unicode="&amp;#x1f316;"/> from "waning_gibbous_moon"<linebreak/>
  <emoji name="wastebasket" unicode="&amp;#x1f5d1;"/> <emoji name="wastebasket" unicode="&amp;#x1f5d1;"/> from "wastebasket"<linebreak/>
  <emoji name="watch" unicode="&amp;#x231a;"/> <emoji name="watch" unicode="&amp;#x231a;"/> from "watch"<linebreak/>
  <emoji name="water_buffalo" unicode="&amp;#x1f403;"/> <emoji name="water_buffalo" unicode="&amp;#x1f403;"/> from "water_buffalo"<linebreak/>
+ <emoji name="water_polo" unicode="&amp;#x1f93d;"/> <emoji name="water_polo" unicode="&amp;#x1f93d;"/> from "water_polo"<linebreak/>
  <emoji name="watermelon" unicode="&amp;#x1f349;"/> <emoji name="watermelon" unicode="&amp;#x1f349;"/> from "watermelon"<linebreak/>
  <emoji name="wave" unicode="&amp;#x1f44b;"/> <emoji name="wave" unicode="&amp;#x1f44b;"/> from "wave"<linebreak/>
  <emoji name="wavy_dash" unicode="&amp;#x3030;"/> <emoji name="wavy_dash" unicode="&amp;#x3030;"/> from "wavy_dash"<linebreak/>
  <emoji name="wc" unicode="&amp;#x1f6be;"/> <emoji name="wc" unicode="&amp;#x1f6be;"/> from "wc"<linebreak/>
  <emoji name="weary" unicode="&amp;#x1f629;"/> <emoji name="weary" unicode="&amp;#x1f629;"/> from "weary"<linebreak/>
  <emoji name="wedding" unicode="&amp;#x1f492;"/> <emoji name="wedding" unicode="&amp;#x1f492;"/> from "wedding"<linebreak/>
- <emoji name="weight_lifting_man" unicode="&amp;#x1f3cb;"/> <emoji name="weight_lifting_man" unicode="&amp;#x1f3cb;"/> from "weight_lifting_man"<linebreak/>
- <emoji name="weight_lifting_woman" unicode="&amp;#x1f3cb;&amp;#x2640;"/> <emoji name="weight_lifting_woman" unicode="&amp;#x1f3cb;&amp;#x2640;"/> from "weight_lifting_woman"<linebreak/>
+ <emoji name="weight_lifting" unicode="&amp;#x1f3cb;"/> <emoji name="weight_lifting" unicode="&amp;#x1f3cb;"/> from "weight_lifting"<linebreak/>
+ <emoji name="weight_lifting_man" unicode="&amp;#x1f3cb;&amp;#xfe0f;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="weight_lifting_man" unicode="&amp;#x1f3cb;&amp;#xfe0f;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "weight_lifting_man"<linebreak/>
+ <emoji name="weight_lifting_woman" unicode="&amp;#x1f3cb;&amp;#xfe0f;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="weight_lifting_woman" unicode="&amp;#x1f3cb;&amp;#xfe0f;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "weight_lifting_woman"<linebreak/>
  <emoji name="western_sahara" unicode="&amp;#x1f1ea;&amp;#x1f1ed;"/> <emoji name="western_sahara" unicode="&amp;#x1f1ea;&amp;#x1f1ed;"/> from "western_sahara"<linebreak/>
  <emoji name="whale" unicode="&amp;#x1f433;"/> <emoji name="whale" unicode="&amp;#x1f433;"/> from "whale"<linebreak/>
  <emoji name="whale2" unicode="&amp;#x1f40b;"/> <emoji name="whale2" unicode="&amp;#x1f40b;"/> from "whale2"<linebreak/>
  <emoji name="white_circle" unicode="&amp;#x26aa;"/> <emoji name="white_circle" unicode="&amp;#x26aa;"/> from "white_circle"<linebreak/>
  <emoji name="white_flag" unicode="&amp;#x1f3f3;"/> <emoji name="white_flag" unicode="&amp;#x1f3f3;"/> from "white_flag"<linebreak/>
  <emoji name="white_flower" unicode="&amp;#x1f4ae;"/> <emoji name="white_flower" unicode="&amp;#x1f4ae;"/> from "white_flower"<linebreak/>
+ <emoji name="white_haired_man" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9b3;"/> <emoji name="white_haired_man" unicode="&amp;#x1f468;&amp;#x200d;&amp;#x1f9b3;"/> from "white_haired_man"<linebreak/>
+ <emoji name="white_haired_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9b3;"/> <emoji name="white_haired_woman" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9b3;"/> from "white_haired_woman"<linebreak/>
+ <emoji name="white_heart" unicode="&amp;#x1f90d;"/> <emoji name="white_heart" unicode="&amp;#x1f90d;"/> from "white_heart"<linebreak/>
  <emoji name="white_large_square" unicode="&amp;#x2b1c;"/> <emoji name="white_large_square" unicode="&amp;#x2b1c;"/> from "white_large_square"<linebreak/>
  <emoji name="white_medium_small_square" unicode="&amp;#x25fd;"/> <emoji name="white_medium_small_square" unicode="&amp;#x25fd;"/> from "white_medium_small_square"<linebreak/>
  <emoji name="white_medium_square" unicode="&amp;#x25fb;"/> <emoji name="white_medium_square" unicode="&amp;#x25fb;"/> from "white_medium_square"<linebreak/>
  <emoji name="wilted_flower" unicode="&amp;#x1f940;"/> <emoji name="wilted_flower" unicode="&amp;#x1f940;"/> from "wilted_flower"<linebreak/>
  <emoji name="wind_chime" unicode="&amp;#x1f390;"/> <emoji name="wind_chime" unicode="&amp;#x1f390;"/> from "wind_chime"<linebreak/>
  <emoji name="wind_face" unicode="&amp;#x1f32c;"/> <emoji name="wind_face" unicode="&amp;#x1f32c;"/> from "wind_face"<linebreak/>
+ <emoji name="window" unicode="&amp;#x1fa9f;"/> <emoji name="window" unicode="&amp;#x1fa9f;"/> from "window"<linebreak/>
  <emoji name="wine_glass" unicode="&amp;#x1f377;"/> <emoji name="wine_glass" unicode="&amp;#x1f377;"/> from "wine_glass"<linebreak/>
  <emoji name="wink" unicode="&amp;#x1f609;"/> <emoji name="wink" unicode="&amp;#x1f609;"/> from "wink"<linebreak/>
  <emoji name="wolf" unicode="&amp;#x1f43a;"/> <emoji name="wolf" unicode="&amp;#x1f43a;"/> from "wolf"<linebreak/>
  <emoji name="woman" unicode="&amp;#x1f469;"/> <emoji name="woman" unicode="&amp;#x1f469;"/> from "woman"<linebreak/>
- <emoji name="woman_artist" unicode="&amp;#x1f469;&amp;#x1f3a8;"/> <emoji name="woman_artist" unicode="&amp;#x1f469;&amp;#x1f3a8;"/> from "woman_artist"<linebreak/>
- <emoji name="woman_astronaut" unicode="&amp;#x1f469;&amp;#x1f680;"/> <emoji name="woman_astronaut" unicode="&amp;#x1f469;&amp;#x1f680;"/> from "woman_astronaut"<linebreak/>
- <emoji name="woman_cartwheeling" unicode="&amp;#x1f938;&amp;#x2640;"/> <emoji name="woman_cartwheeling" unicode="&amp;#x1f938;&amp;#x2640;"/> from "woman_cartwheeling"<linebreak/>
- <emoji name="woman_cook" unicode="&amp;#x1f469;&amp;#x1f373;"/> <emoji name="woman_cook" unicode="&amp;#x1f469;&amp;#x1f373;"/> from "woman_cook"<linebreak/>
- <emoji name="woman_facepalming" unicode="&amp;#x1f926;&amp;#x2640;"/> <emoji name="woman_facepalming" unicode="&amp;#x1f926;&amp;#x2640;"/> from "woman_facepalming"<linebreak/>
- <emoji name="woman_factory_worker" unicode="&amp;#x1f469;&amp;#x1f3ed;"/> <emoji name="woman_factory_worker" unicode="&amp;#x1f469;&amp;#x1f3ed;"/> from "woman_factory_worker"<linebreak/>
- <emoji name="woman_farmer" unicode="&amp;#x1f469;&amp;#x1f33e;"/> <emoji name="woman_farmer" unicode="&amp;#x1f469;&amp;#x1f33e;"/> from "woman_farmer"<linebreak/>
- <emoji name="woman_firefighter" unicode="&amp;#x1f469;&amp;#x1f692;"/> <emoji name="woman_firefighter" unicode="&amp;#x1f469;&amp;#x1f692;"/> from "woman_firefighter"<linebreak/>
- <emoji name="woman_health_worker" unicode="&amp;#x1f469;&amp;#x2695;"/> <emoji name="woman_health_worker" unicode="&amp;#x1f469;&amp;#x2695;"/> from "woman_health_worker"<linebreak/>
- <emoji name="woman_judge" unicode="&amp;#x1f469;&amp;#x2696;"/> <emoji name="woman_judge" unicode="&amp;#x1f469;&amp;#x2696;"/> from "woman_judge"<linebreak/>
- <emoji name="woman_juggling" unicode="&amp;#x1f939;&amp;#x2640;"/> <emoji name="woman_juggling" unicode="&amp;#x1f939;&amp;#x2640;"/> from "woman_juggling"<linebreak/>
- <emoji name="woman_mechanic" unicode="&amp;#x1f469;&amp;#x1f527;"/> <emoji name="woman_mechanic" unicode="&amp;#x1f469;&amp;#x1f527;"/> from "woman_mechanic"<linebreak/>
- <emoji name="woman_office_worker" unicode="&amp;#x1f469;&amp;#x1f4bc;"/> <emoji name="woman_office_worker" unicode="&amp;#x1f469;&amp;#x1f4bc;"/> from "woman_office_worker"<linebreak/>
- <emoji name="woman_pilot" unicode="&amp;#x1f469;&amp;#x2708;"/> <emoji name="woman_pilot" unicode="&amp;#x1f469;&amp;#x2708;"/> from "woman_pilot"<linebreak/>
- <emoji name="woman_playing_handball" unicode="&amp;#x1f93e;&amp;#x2640;"/> <emoji name="woman_playing_handball" unicode="&amp;#x1f93e;&amp;#x2640;"/> from "woman_playing_handball"<linebreak/>
- <emoji name="woman_playing_water_polo" unicode="&amp;#x1f93d;&amp;#x2640;"/> <emoji name="woman_playing_water_polo" unicode="&amp;#x1f93d;&amp;#x2640;"/> from "woman_playing_water_polo"<linebreak/>
- <emoji name="woman_scientist" unicode="&amp;#x1f469;&amp;#x1f52c;"/> <emoji name="woman_scientist" unicode="&amp;#x1f469;&amp;#x1f52c;"/> from "woman_scientist"<linebreak/>
- <emoji name="woman_shrugging" unicode="&amp;#x1f937;&amp;#x2640;"/> <emoji name="woman_shrugging" unicode="&amp;#x1f937;&amp;#x2640;"/> from "woman_shrugging"<linebreak/>
- <emoji name="woman_singer" unicode="&amp;#x1f469;&amp;#x1f3a4;"/> <emoji name="woman_singer" unicode="&amp;#x1f469;&amp;#x1f3a4;"/> from "woman_singer"<linebreak/>
- <emoji name="woman_student" unicode="&amp;#x1f469;&amp;#x1f393;"/> <emoji name="woman_student" unicode="&amp;#x1f469;&amp;#x1f393;"/> from "woman_student"<linebreak/>
- <emoji name="woman_teacher" unicode="&amp;#x1f469;&amp;#x1f3eb;"/> <emoji name="woman_teacher" unicode="&amp;#x1f469;&amp;#x1f3eb;"/> from "woman_teacher"<linebreak/>
- <emoji name="woman_technologist" unicode="&amp;#x1f469;&amp;#x1f4bb;"/> <emoji name="woman_technologist" unicode="&amp;#x1f469;&amp;#x1f4bb;"/> from "woman_technologist"<linebreak/>
- <emoji name="woman_with_turban" unicode="&amp;#x1f473;&amp;#x2640;"/> <emoji name="woman_with_turban" unicode="&amp;#x1f473;&amp;#x2640;"/> from "woman_with_turban"<linebreak/>
+ <emoji name="woman_artist" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f3a8;"/> <emoji name="woman_artist" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f3a8;"/> from "woman_artist"<linebreak/>
+ <emoji name="woman_astronaut" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f680;"/> <emoji name="woman_astronaut" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f680;"/> from "woman_astronaut"<linebreak/>
+ <emoji name="woman_beard" unicode="&amp;#x1f9d4;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="woman_beard" unicode="&amp;#x1f9d4;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "woman_beard"<linebreak/>
+ <emoji name="woman_cartwheeling" unicode="&amp;#x1f938;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="woman_cartwheeling" unicode="&amp;#x1f938;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "woman_cartwheeling"<linebreak/>
+ <emoji name="woman_cook" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f373;"/> <emoji name="woman_cook" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f373;"/> from "woman_cook"<linebreak/>
+ <emoji name="woman_dancing" unicode="&amp;#x1f483;"/> <emoji name="woman_dancing" unicode="&amp;#x1f483;"/> from "woman_dancing"<linebreak/>
+ <emoji name="woman_facepalming" unicode="&amp;#x1f926;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="woman_facepalming" unicode="&amp;#x1f926;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "woman_facepalming"<linebreak/>
+ <emoji name="woman_factory_worker" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f3ed;"/> <emoji name="woman_factory_worker" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f3ed;"/> from "woman_factory_worker"<linebreak/>
+ <emoji name="woman_farmer" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f33e;"/> <emoji name="woman_farmer" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f33e;"/> from "woman_farmer"<linebreak/>
+ <emoji name="woman_feeding_baby" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f37c;"/> <emoji name="woman_feeding_baby" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f37c;"/> from "woman_feeding_baby"<linebreak/>
+ <emoji name="woman_firefighter" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f692;"/> <emoji name="woman_firefighter" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f692;"/> from "woman_firefighter"<linebreak/>
+ <emoji name="woman_health_worker" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2695;&amp;#xfe0f;"/> <emoji name="woman_health_worker" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2695;&amp;#xfe0f;"/> from "woman_health_worker"<linebreak/>
+ <emoji name="woman_in_manual_wheelchair" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9bd;"/> <emoji name="woman_in_manual_wheelchair" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9bd;"/> from "woman_in_manual_wheelchair"<linebreak/>
+ <emoji name="woman_in_motorized_wheelchair" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9bc;"/> <emoji name="woman_in_motorized_wheelchair" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9bc;"/> from "woman_in_motorized_wheelchair"<linebreak/>
+ <emoji name="woman_in_tuxedo" unicode="&amp;#x1f935;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="woman_in_tuxedo" unicode="&amp;#x1f935;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "woman_in_tuxedo"<linebreak/>
+ <emoji name="woman_judge" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2696;&amp;#xfe0f;"/> <emoji name="woman_judge" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2696;&amp;#xfe0f;"/> from "woman_judge"<linebreak/>
+ <emoji name="woman_juggling" unicode="&amp;#x1f939;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="woman_juggling" unicode="&amp;#x1f939;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "woman_juggling"<linebreak/>
+ <emoji name="woman_mechanic" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f527;"/> <emoji name="woman_mechanic" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f527;"/> from "woman_mechanic"<linebreak/>
+ <emoji name="woman_office_worker" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f4bc;"/> <emoji name="woman_office_worker" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f4bc;"/> from "woman_office_worker"<linebreak/>
+ <emoji name="woman_pilot" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2708;&amp;#xfe0f;"/> <emoji name="woman_pilot" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x2708;&amp;#xfe0f;"/> from "woman_pilot"<linebreak/>
+ <emoji name="woman_playing_handball" unicode="&amp;#x1f93e;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="woman_playing_handball" unicode="&amp;#x1f93e;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "woman_playing_handball"<linebreak/>
+ <emoji name="woman_playing_water_polo" unicode="&amp;#x1f93d;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="woman_playing_water_polo" unicode="&amp;#x1f93d;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "woman_playing_water_polo"<linebreak/>
+ <emoji name="woman_scientist" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f52c;"/> <emoji name="woman_scientist" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f52c;"/> from "woman_scientist"<linebreak/>
+ <emoji name="woman_shrugging" unicode="&amp;#x1f937;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="woman_shrugging" unicode="&amp;#x1f937;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "woman_shrugging"<linebreak/>
+ <emoji name="woman_singer" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f3a4;"/> <emoji name="woman_singer" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f3a4;"/> from "woman_singer"<linebreak/>
+ <emoji name="woman_student" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f393;"/> <emoji name="woman_student" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f393;"/> from "woman_student"<linebreak/>
+ <emoji name="woman_teacher" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f3eb;"/> <emoji name="woman_teacher" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f3eb;"/> from "woman_teacher"<linebreak/>
+ <emoji name="woman_technologist" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f4bb;"/> <emoji name="woman_technologist" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f4bb;"/> from "woman_technologist"<linebreak/>
+ <emoji name="woman_with_headscarf" unicode="&amp;#x1f9d5;"/> <emoji name="woman_with_headscarf" unicode="&amp;#x1f9d5;"/> from "woman_with_headscarf"<linebreak/>
+ <emoji name="woman_with_probing_cane" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9af;"/> <emoji name="woman_with_probing_cane" unicode="&amp;#x1f469;&amp;#x200d;&amp;#x1f9af;"/> from "woman_with_probing_cane"<linebreak/>
+ <emoji name="woman_with_turban" unicode="&amp;#x1f473;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="woman_with_turban" unicode="&amp;#x1f473;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "woman_with_turban"<linebreak/>
+ <emoji name="woman_with_veil" unicode="&amp;#x1f470;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="woman_with_veil" unicode="&amp;#x1f470;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "woman_with_veil"<linebreak/>
  <emoji name="womans_clothes" unicode="&amp;#x1f45a;"/> <emoji name="womans_clothes" unicode="&amp;#x1f45a;"/> from "womans_clothes"<linebreak/>
  <emoji name="womans_hat" unicode="&amp;#x1f452;"/> <emoji name="womans_hat" unicode="&amp;#x1f452;"/> from "womans_hat"<linebreak/>
- <emoji name="women_wrestling" unicode="&amp;#x1f93c;&amp;#x2640;"/> <emoji name="women_wrestling" unicode="&amp;#x1f93c;&amp;#x2640;"/> from "women_wrestling"<linebreak/>
+ <emoji name="women_wrestling" unicode="&amp;#x1f93c;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="women_wrestling" unicode="&amp;#x1f93c;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "women_wrestling"<linebreak/>
  <emoji name="womens" unicode="&amp;#x1f6ba;"/> <emoji name="womens" unicode="&amp;#x1f6ba;"/> from "womens"<linebreak/>
+ <emoji name="wood" unicode="&amp;#x1fab5;"/> <emoji name="wood" unicode="&amp;#x1fab5;"/> from "wood"<linebreak/>
+ <emoji name="woozy_face" unicode="&amp;#x1f974;"/> <emoji name="woozy_face" unicode="&amp;#x1f974;"/> from "woozy_face"<linebreak/>
  <emoji name="world_map" unicode="&amp;#x1f5fa;"/> <emoji name="world_map" unicode="&amp;#x1f5fa;"/> from "world_map"<linebreak/>
+ <emoji name="worm" unicode="&amp;#x1fab1;"/> <emoji name="worm" unicode="&amp;#x1fab1;"/> from "worm"<linebreak/>
  <emoji name="worried" unicode="&amp;#x1f61f;"/> <emoji name="worried" unicode="&amp;#x1f61f;"/> from "worried"<linebreak/>
  <emoji name="wrench" unicode="&amp;#x1f527;"/> <emoji name="wrench" unicode="&amp;#x1f527;"/> from "wrench"<linebreak/>
+ <emoji name="wrestling" unicode="&amp;#x1f93c;"/> <emoji name="wrestling" unicode="&amp;#x1f93c;"/> from "wrestling"<linebreak/>
  <emoji name="writing_hand" unicode="&amp;#x270d;"/> <emoji name="writing_hand" unicode="&amp;#x270d;"/> from "writing_hand"<linebreak/>
  <emoji name="x" unicode="&amp;#x274c;"/> <emoji name="x" unicode="&amp;#x274c;"/> from "x"<linebreak/>
+ <emoji name="yarn" unicode="&amp;#x1f9f6;"/> <emoji name="yarn" unicode="&amp;#x1f9f6;"/> from "yarn"<linebreak/>
+ <emoji name="yawning_face" unicode="&amp;#x1f971;"/> <emoji name="yawning_face" unicode="&amp;#x1f971;"/> from "yawning_face"<linebreak/>
+ <emoji name="yellow_circle" unicode="&amp;#x1f7e1;"/> <emoji name="yellow_circle" unicode="&amp;#x1f7e1;"/> from "yellow_circle"<linebreak/>
  <emoji name="yellow_heart" unicode="&amp;#x1f49b;"/> <emoji name="yellow_heart" unicode="&amp;#x1f49b;"/> from "yellow_heart"<linebreak/>
+ <emoji name="yellow_square" unicode="&amp;#x1f7e8;"/> <emoji name="yellow_square" unicode="&amp;#x1f7e8;"/> from "yellow_square"<linebreak/>
  <emoji name="yemen" unicode="&amp;#x1f1fe;&amp;#x1f1ea;"/> <emoji name="yemen" unicode="&amp;#x1f1fe;&amp;#x1f1ea;"/> from "yemen"<linebreak/>
  <emoji name="yen" unicode="&amp;#x1f4b4;"/> <emoji name="yen" unicode="&amp;#x1f4b4;"/> from "yen"<linebreak/>
  <emoji name="yin_yang" unicode="&amp;#x262f;"/> <emoji name="yin_yang" unicode="&amp;#x262f;"/> from "yin_yang"<linebreak/>
+ <emoji name="yo_yo" unicode="&amp;#x1fa80;"/> <emoji name="yo_yo" unicode="&amp;#x1fa80;"/> from "yo_yo"<linebreak/>
  <emoji name="yum" unicode="&amp;#x1f60b;"/> <emoji name="yum" unicode="&amp;#x1f60b;"/> from "yum"<linebreak/>
  <emoji name="zambia" unicode="&amp;#x1f1ff;&amp;#x1f1f2;"/> <emoji name="zambia" unicode="&amp;#x1f1ff;&amp;#x1f1f2;"/> from "zambia"<linebreak/>
+ <emoji name="zany_face" unicode="&amp;#x1f92a;"/> <emoji name="zany_face" unicode="&amp;#x1f92a;"/> from "zany_face"<linebreak/>
  <emoji name="zap" unicode="&amp;#x26a1;"/> <emoji name="zap" unicode="&amp;#x26a1;"/> from "zap"<linebreak/>
- <emoji name="zero" unicode="&amp;#x0030;&amp;#x20e3;"/> <emoji name="zero" unicode="&amp;#x0030;&amp;#x20e3;"/> from "zero"<linebreak/>
+ <emoji name="zebra" unicode="&amp;#x1f993;"/> <emoji name="zebra" unicode="&amp;#x1f993;"/> from "zebra"<linebreak/>
+ <emoji name="zero" unicode="&amp;#x0030;&amp;#xfe0f;&amp;#x20e3;"/> <emoji name="zero" unicode="&amp;#x0030;&amp;#xfe0f;&amp;#x20e3;"/> from "zero"<linebreak/>
  <emoji name="zimbabwe" unicode="&amp;#x1f1ff;&amp;#x1f1fc;"/> <emoji name="zimbabwe" unicode="&amp;#x1f1ff;&amp;#x1f1fc;"/> from "zimbabwe"<linebreak/>
  <emoji name="zipper_mouth_face" unicode="&amp;#x1f910;"/> <emoji name="zipper_mouth_face" unicode="&amp;#x1f910;"/> from "zipper_mouth_face"<linebreak/>
+ <emoji name="zombie" unicode="&amp;#x1f9df;"/> <emoji name="zombie" unicode="&amp;#x1f9df;"/> from "zombie"<linebreak/>
+ <emoji name="zombie_man" unicode="&amp;#x1f9df;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="zombie_man" unicode="&amp;#x1f9df;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "zombie_man"<linebreak/>
+ <emoji name="zombie_woman" unicode="&amp;#x1f9df;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> <emoji name="zombie_woman" unicode="&amp;#x1f9df;&amp;#x200d;&amp;#x2640;&amp;#xfe0f;"/> from "zombie_woman"<linebreak/>
  <emoji name="zzz" unicode="&amp;#x1f4a4;"/> <emoji name="zzz" unicode="&amp;#x1f4a4;"/> from "zzz"<linebreak/>
+ <emoji name="blond_haired_man" unicode="&amp;#x1f471;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> <emoji name="blond_haired_man" unicode="&amp;#x1f471;&amp;#x200d;&amp;#x2642;&amp;#xfe0f;"/> from "blonde_man"<linebreak/>
+ <emoji name="frowning_person" unicode="&amp;#x1f64d;"/> <emoji name="frowning_person" unicode="&amp;#x1f64d;"/> from "person_frowning"<linebreak/>
+ <emoji name="blond_haired_person" unicode="&amp;#x1f471;"/> <emoji name="blond_haired_person" unicode="&amp;#x1f471;"/> from "person_with_blond_hair"<linebreak/>
+ <emoji name="pouting_face" unicode="&amp;#x1f64e;"/> <emoji name="pouting_face" unicode="&amp;#x1f64e;"/> from "person_with_pouting_face"<linebreak/>
  </para>
     </detaileddescription>
     <location file="076_emojis.cpp"/>
old mode 100644 (file)
new mode 100755 (executable)
index 0526ebe..736e410
   @emoji 8ball   @emoji :8ball: from "8ball"<br>
   @emoji a   @emoji :a: from "a"<br>
   @emoji ab   @emoji :ab: from "ab"<br>
+  @emoji abacus   @emoji :abacus: from "abacus"<br>
   @emoji abc   @emoji :abc: from "abc"<br>
   @emoji abcd   @emoji :abcd: from "abcd"<br>
   @emoji accept   @emoji :accept: from "accept"<br>
+  @emoji accordion   @emoji :accordion: from "accordion"<br>
+  @emoji adhesive_bandage   @emoji :adhesive_bandage: from "adhesive_bandage"<br>
+  @emoji adult   @emoji :adult: from "adult"<br>
   @emoji aerial_tramway   @emoji :aerial_tramway: from "aerial_tramway"<br>
   @emoji afghanistan   @emoji :afghanistan: from "afghanistan"<br>
   @emoji airplane   @emoji :airplane: from "airplane"<br>
@@ -27,6 +31,7 @@
   @emoji ambulance   @emoji :ambulance: from "ambulance"<br>
   @emoji american_samoa   @emoji :american_samoa: from "american_samoa"<br>
   @emoji amphora   @emoji :amphora: from "amphora"<br>
+  @emoji anatomical_heart   @emoji :anatomical_heart: from "anatomical_heart"<br>
   @emoji anchor   @emoji :anchor: from "anchor"<br>
   @emoji andorra   @emoji :andorra: from "andorra"<br>
   @emoji angel   @emoji :angel: from "angel"<br>
   @emoji art   @emoji :art: from "art"<br>
   @emoji articulated_lorry   @emoji :articulated_lorry: from "articulated_lorry"<br>
   @emoji artificial_satellite   @emoji :artificial_satellite: from "artificial_satellite"<br>
+  @emoji artist   @emoji :artist: from "artist"<br>
   @emoji aruba   @emoji :aruba: from "aruba"<br>
+  @emoji ascension_island   @emoji :ascension_island: from "ascension_island"<br>
   @emoji asterisk   @emoji :asterisk: from "asterisk"<br>
   @emoji astonished   @emoji :astonished: from "astonished"<br>
+  @emoji astronaut   @emoji :astronaut: from "astronaut"<br>
   @emoji athletic_shoe   @emoji :athletic_shoe: from "athletic_shoe"<br>
   @emoji atm   @emoji :atm: from "atm"<br>
   @emoji atom_symbol   @emoji :atom_symbol: from "atom_symbol"<br>
   @emoji australia   @emoji :australia: from "australia"<br>
   @emoji austria   @emoji :austria: from "austria"<br>
+  @emoji auto_rickshaw   @emoji :auto_rickshaw: from "auto_rickshaw"<br>
   @emoji avocado   @emoji :avocado: from "avocado"<br>
+  @emoji axe   @emoji :axe: from "axe"<br>
   @emoji azerbaijan   @emoji :azerbaijan: from "azerbaijan"<br>
   @emoji b   @emoji :b: from "b"<br>
   @emoji baby   @emoji :baby: from "baby"<br>
   @emoji baby_symbol   @emoji :baby_symbol: from "baby_symbol"<br>
   @emoji back   @emoji :back: from "back"<br>
   @emoji bacon   @emoji :bacon: from "bacon"<br>
+  @emoji badger   @emoji :badger: from "badger"<br>
   @emoji badminton   @emoji :badminton: from "badminton"<br>
+  @emoji bagel   @emoji :bagel: from "bagel"<br>
   @emoji baggage_claim   @emoji :baggage_claim: from "baggage_claim"<br>
   @emoji baguette_bread   @emoji :baguette_bread: from "baguette_bread"<br>
   @emoji bahamas   @emoji :bahamas: from "bahamas"<br>
   @emoji bahrain   @emoji :bahrain: from "bahrain"<br>
   @emoji balance_scale   @emoji :balance_scale: from "balance_scale"<br>
+  @emoji bald_man   @emoji :bald_man: from "bald_man"<br>
+  @emoji bald_woman   @emoji :bald_woman: from "bald_woman"<br>
+  @emoji ballet_shoes   @emoji :ballet_shoes: from "ballet_shoes"<br>
   @emoji balloon   @emoji :balloon: from "balloon"<br>
   @emoji ballot_box   @emoji :ballot_box: from "ballot_box"<br>
   @emoji ballot_box_with_check   @emoji :ballot_box_with_check: from "ballot_box_with_check"<br>
   @emoji banana   @emoji :banana: from "banana"<br>
   @emoji bangbang   @emoji :bangbang: from "bangbang"<br>
   @emoji bangladesh   @emoji :bangladesh: from "bangladesh"<br>
+  @emoji banjo   @emoji :banjo: from "banjo"<br>
   @emoji bank   @emoji :bank: from "bank"<br>
   @emoji bar_chart   @emoji :bar_chart: from "bar_chart"<br>
   @emoji barbados   @emoji :barbados: from "barbados"<br>
   @emoji barber   @emoji :barber: from "barber"<br>
   @emoji baseball   @emoji :baseball: from "baseball"<br>
+  @emoji basket   @emoji :basket: from "basket"<br>
   @emoji basketball   @emoji :basketball: from "basketball"<br>
   @emoji basketball_man   @emoji :basketball_man: from "basketball_man"<br>
   @emoji basketball_woman   @emoji :basketball_woman: from "basketball_woman"<br>
   @emoji battery   @emoji :battery: from "battery"<br>
   @emoji beach_umbrella   @emoji :beach_umbrella: from "beach_umbrella"<br>
   @emoji bear   @emoji :bear: from "bear"<br>
+  @emoji bearded_person   @emoji :bearded_person: from "bearded_person"<br>
+  @emoji beaver   @emoji :beaver: from "beaver"<br>
   @emoji bed   @emoji :bed: from "bed"<br>
   @emoji bee   @emoji :bee: from "bee"<br>
   @emoji beer   @emoji :beer: from "beer"<br>
   @emoji belgium   @emoji :belgium: from "belgium"<br>
   @emoji belize   @emoji :belize: from "belize"<br>
   @emoji bell   @emoji :bell: from "bell"<br>
+  @emoji bell_pepper   @emoji :bell_pepper: from "bell_pepper"<br>
   @emoji bellhop_bell   @emoji :bellhop_bell: from "bellhop_bell"<br>
   @emoji benin   @emoji :benin: from "benin"<br>
   @emoji bento   @emoji :bento: from "bento"<br>
   @emoji bermuda   @emoji :bermuda: from "bermuda"<br>
+  @emoji beverage_box   @emoji :beverage_box: from "beverage_box"<br>
   @emoji bhutan   @emoji :bhutan: from "bhutan"<br>
   @emoji bicyclist   @emoji :bicyclist: from "bicyclist"<br>
   @emoji bike   @emoji :bike: from "bike"<br>
   @emoji biking_man   @emoji :biking_man: from "biking_man"<br>
   @emoji biking_woman   @emoji :biking_woman: from "biking_woman"<br>
   @emoji bikini   @emoji :bikini: from "bikini"<br>
+  @emoji billed_cap   @emoji :billed_cap: from "billed_cap"<br>
   @emoji biohazard   @emoji :biohazard: from "biohazard"<br>
   @emoji bird   @emoji :bird: from "bird"<br>
   @emoji birthday   @emoji :birthday: from "birthday"<br>
+  @emoji bison   @emoji :bison: from "bison"<br>
+  @emoji black_cat   @emoji :black_cat: from "black_cat"<br>
   @emoji black_circle   @emoji :black_circle: from "black_circle"<br>
   @emoji black_flag   @emoji :black_flag: from "black_flag"<br>
   @emoji black_heart   @emoji :black_heart: from "black_heart"<br>
   @emoji black_nib   @emoji :black_nib: from "black_nib"<br>
   @emoji black_small_square   @emoji :black_small_square: from "black_small_square"<br>
   @emoji black_square_button   @emoji :black_square_button: from "black_square_button"<br>
-  @emoji blonde_man   @emoji :blonde_man: from "blonde_man"<br>
+  @emoji blond_haired_man   @emoji :blond_haired_man: from "blond_haired_man"<br>
+  @emoji blond_haired_person   @emoji :blond_haired_person: from "blond_haired_person"<br>
+  @emoji blond_haired_woman   @emoji :blond_haired_woman: from "blond_haired_woman"<br>
   @emoji blonde_woman   @emoji :blonde_woman: from "blonde_woman"<br>
   @emoji blossom   @emoji :blossom: from "blossom"<br>
   @emoji blowfish   @emoji :blowfish: from "blowfish"<br>
   @emoji blue_book   @emoji :blue_book: from "blue_book"<br>
   @emoji blue_car   @emoji :blue_car: from "blue_car"<br>
   @emoji blue_heart   @emoji :blue_heart: from "blue_heart"<br>
+  @emoji blue_square   @emoji :blue_square: from "blue_square"<br>
+  @emoji blueberries   @emoji :blueberries: from "blueberries"<br>
   @emoji blush   @emoji :blush: from "blush"<br>
   @emoji boar   @emoji :boar: from "boar"<br>
   @emoji boat   @emoji :boat: from "boat"<br>
   @emoji bolivia   @emoji :bolivia: from "bolivia"<br>
   @emoji bomb   @emoji :bomb: from "bomb"<br>
+  @emoji bone   @emoji :bone: from "bone"<br>
   @emoji book   @emoji :book: from "book"<br>
   @emoji bookmark   @emoji :bookmark: from "bookmark"<br>
   @emoji bookmark_tabs   @emoji :bookmark_tabs: from "bookmark_tabs"<br>
   @emoji books   @emoji :books: from "books"<br>
   @emoji boom   @emoji :boom: from "boom"<br>
+  @emoji boomerang   @emoji :boomerang: from "boomerang"<br>
   @emoji boot   @emoji :boot: from "boot"<br>
   @emoji bosnia_herzegovina   @emoji :bosnia_herzegovina: from "bosnia_herzegovina"<br>
   @emoji botswana   @emoji :botswana: from "botswana"<br>
+  @emoji bouncing_ball_man   @emoji :bouncing_ball_man: from "bouncing_ball_man"<br>
+  @emoji bouncing_ball_person   @emoji :bouncing_ball_person: from "bouncing_ball_person"<br>
+  @emoji bouncing_ball_woman   @emoji :bouncing_ball_woman: from "bouncing_ball_woman"<br>
   @emoji bouquet   @emoji :bouquet: from "bouquet"<br>
+  @emoji bouvet_island   @emoji :bouvet_island: from "bouvet_island"<br>
   @emoji bow   @emoji :bow: from "bow"<br>
   @emoji bow_and_arrow   @emoji :bow_and_arrow: from "bow_and_arrow"<br>
   @emoji bowing_man   @emoji :bowing_man: from "bowing_man"<br>
   @emoji bowing_woman   @emoji :bowing_woman: from "bowing_woman"<br>
+  @emoji bowl_with_spoon   @emoji :bowl_with_spoon: from "bowl_with_spoon"<br>
   @emoji bowling   @emoji :bowling: from "bowling"<br>
   @emoji boxing_glove   @emoji :boxing_glove: from "boxing_glove"<br>
   @emoji boy   @emoji :boy: from "boy"<br>
+  @emoji brain   @emoji :brain: from "brain"<br>
   @emoji brazil   @emoji :brazil: from "brazil"<br>
   @emoji bread   @emoji :bread: from "bread"<br>
+  @emoji breast_feeding   @emoji :breast_feeding: from "breast_feeding"<br>
+  @emoji bricks   @emoji :bricks: from "bricks"<br>
   @emoji bride_with_veil   @emoji :bride_with_veil: from "bride_with_veil"<br>
   @emoji bridge_at_night   @emoji :bridge_at_night: from "bridge_at_night"<br>
   @emoji briefcase   @emoji :briefcase: from "briefcase"<br>
   @emoji british_indian_ocean_territory   @emoji :british_indian_ocean_territory: from "british_indian_ocean_territory"<br>
   @emoji british_virgin_islands   @emoji :british_virgin_islands: from "british_virgin_islands"<br>
+  @emoji broccoli   @emoji :broccoli: from "broccoli"<br>
   @emoji broken_heart   @emoji :broken_heart: from "broken_heart"<br>
+  @emoji broom   @emoji :broom: from "broom"<br>
+  @emoji brown_circle   @emoji :brown_circle: from "brown_circle"<br>
+  @emoji brown_heart   @emoji :brown_heart: from "brown_heart"<br>
+  @emoji brown_square   @emoji :brown_square: from "brown_square"<br>
   @emoji brunei   @emoji :brunei: from "brunei"<br>
+  @emoji bubble_tea   @emoji :bubble_tea: from "bubble_tea"<br>
+  @emoji bucket   @emoji :bucket: from "bucket"<br>
   @emoji bug   @emoji :bug: from "bug"<br>
   @emoji building_construction   @emoji :building_construction: from "building_construction"<br>
   @emoji bulb   @emoji :bulb: from "bulb"<br>
   @emoji busstop   @emoji :busstop: from "busstop"<br>
   @emoji bust_in_silhouette   @emoji :bust_in_silhouette: from "bust_in_silhouette"<br>
   @emoji busts_in_silhouette   @emoji :busts_in_silhouette: from "busts_in_silhouette"<br>
+  @emoji butter   @emoji :butter: from "butter"<br>
   @emoji butterfly   @emoji :butterfly: from "butterfly"<br>
   @emoji cactus   @emoji :cactus: from "cactus"<br>
   @emoji cake   @emoji :cake: from "cake"<br>
   @emoji cancer   @emoji :cancer: from "cancer"<br>
   @emoji candle   @emoji :candle: from "candle"<br>
   @emoji candy   @emoji :candy: from "candy"<br>
+  @emoji canned_food   @emoji :canned_food: from "canned_food"<br>
   @emoji canoe   @emoji :canoe: from "canoe"<br>
   @emoji cape_verde   @emoji :cape_verde: from "cape_verde"<br>
   @emoji capital_abcd   @emoji :capital_abcd: from "capital_abcd"<br>
   @emoji card_index_dividers   @emoji :card_index_dividers: from "card_index_dividers"<br>
   @emoji caribbean_netherlands   @emoji :caribbean_netherlands: from "caribbean_netherlands"<br>
   @emoji carousel_horse   @emoji :carousel_horse: from "carousel_horse"<br>
+  @emoji carpentry_saw   @emoji :carpentry_saw: from "carpentry_saw"<br>
   @emoji carrot   @emoji :carrot: from "carrot"<br>
+  @emoji cartwheeling   @emoji :cartwheeling: from "cartwheeling"<br>
   @emoji cat   @emoji :cat: from "cat"<br>
   @emoji cat2   @emoji :cat2: from "cat2"<br>
   @emoji cayman_islands   @emoji :cayman_islands: from "cayman_islands"<br>
   @emoji cd   @emoji :cd: from "cd"<br>
   @emoji central_african_republic   @emoji :central_african_republic: from "central_african_republic"<br>
+  @emoji ceuta_melilla   @emoji :ceuta_melilla: from "ceuta_melilla"<br>
   @emoji chad   @emoji :chad: from "chad"<br>
   @emoji chains   @emoji :chains: from "chains"<br>
+  @emoji chair   @emoji :chair: from "chair"<br>
   @emoji champagne   @emoji :champagne: from "champagne"<br>
   @emoji chart   @emoji :chart: from "chart"<br>
   @emoji chart_with_downwards_trend   @emoji :chart_with_downwards_trend: from "chart_with_downwards_trend"<br>
   @emoji cheese   @emoji :cheese: from "cheese"<br>
   @emoji cherries   @emoji :cherries: from "cherries"<br>
   @emoji cherry_blossom   @emoji :cherry_blossom: from "cherry_blossom"<br>
+  @emoji chess_pawn   @emoji :chess_pawn: from "chess_pawn"<br>
   @emoji chestnut   @emoji :chestnut: from "chestnut"<br>
   @emoji chicken   @emoji :chicken: from "chicken"<br>
+  @emoji child   @emoji :child: from "child"<br>
   @emoji children_crossing   @emoji :children_crossing: from "children_crossing"<br>
   @emoji chile   @emoji :chile: from "chile"<br>
   @emoji chipmunk   @emoji :chipmunk: from "chipmunk"<br>
   @emoji chocolate_bar   @emoji :chocolate_bar: from "chocolate_bar"<br>
+  @emoji chopsticks   @emoji :chopsticks: from "chopsticks"<br>
   @emoji christmas_island   @emoji :christmas_island: from "christmas_island"<br>
   @emoji christmas_tree   @emoji :christmas_tree: from "christmas_tree"<br>
   @emoji church   @emoji :church: from "church"<br>
   @emoji clap   @emoji :clap: from "clap"<br>
   @emoji clapper   @emoji :clapper: from "clapper"<br>
   @emoji classical_building   @emoji :classical_building: from "classical_building"<br>
+  @emoji climbing   @emoji :climbing: from "climbing"<br>
+  @emoji climbing_man   @emoji :climbing_man: from "climbing_man"<br>
+  @emoji climbing_woman   @emoji :climbing_woman: from "climbing_woman"<br>
   @emoji clinking_glasses   @emoji :clinking_glasses: from "clinking_glasses"<br>
   @emoji clipboard   @emoji :clipboard: from "clipboard"<br>
+  @emoji clipperton_island   @emoji :clipperton_island: from "clipperton_island"<br>
   @emoji clock1   @emoji :clock1: from "clock1"<br>
   @emoji clock10   @emoji :clock10: from "clock10"<br>
   @emoji clock1030   @emoji :clock1030: from "clock1030"<br>
   @emoji clown_face   @emoji :clown_face: from "clown_face"<br>
   @emoji clubs   @emoji :clubs: from "clubs"<br>
   @emoji cn   @emoji :cn: from "cn"<br>
+  @emoji coat   @emoji :coat: from "coat"<br>
+  @emoji cockroach   @emoji :cockroach: from "cockroach"<br>
   @emoji cocktail   @emoji :cocktail: from "cocktail"<br>
+  @emoji coconut   @emoji :coconut: from "coconut"<br>
   @emoji cocos_islands   @emoji :cocos_islands: from "cocos_islands"<br>
   @emoji coffee   @emoji :coffee: from "coffee"<br>
   @emoji coffin   @emoji :coffin: from "coffin"<br>
+  @emoji coin   @emoji :coin: from "coin"<br>
+  @emoji cold_face   @emoji :cold_face: from "cold_face"<br>
   @emoji cold_sweat   @emoji :cold_sweat: from "cold_sweat"<br>
   @emoji collision   @emoji :collision: from "collision"<br>
   @emoji colombia   @emoji :colombia: from "colombia"<br>
   @emoji comet   @emoji :comet: from "comet"<br>
   @emoji comoros   @emoji :comoros: from "comoros"<br>
+  @emoji compass   @emoji :compass: from "compass"<br>
   @emoji computer   @emoji :computer: from "computer"<br>
   @emoji computer_mouse   @emoji :computer_mouse: from "computer_mouse"<br>
   @emoji confetti_ball   @emoji :confetti_ball: from "confetti_ball"<br>
   @emoji construction_worker_woman   @emoji :construction_worker_woman: from "construction_worker_woman"<br>
   @emoji control_knobs   @emoji :control_knobs: from "control_knobs"<br>
   @emoji convenience_store   @emoji :convenience_store: from "convenience_store"<br>
+  @emoji cook   @emoji :cook: from "cook"<br>
   @emoji cook_islands   @emoji :cook_islands: from "cook_islands"<br>
   @emoji cookie   @emoji :cookie: from "cookie"<br>
   @emoji cool   @emoji :cool: from "cool"<br>
   @emoji couple_with_heart_man_man   @emoji :couple_with_heart_man_man: from "couple_with_heart_man_man"<br>
   @emoji couple_with_heart_woman_man   @emoji :couple_with_heart_woman_man: from "couple_with_heart_woman_man"<br>
   @emoji couple_with_heart_woman_woman   @emoji :couple_with_heart_woman_woman: from "couple_with_heart_woman_woman"<br>
+  @emoji couplekiss   @emoji :couplekiss: from "couplekiss"<br>
   @emoji couplekiss_man_man   @emoji :couplekiss_man_man: from "couplekiss_man_man"<br>
   @emoji couplekiss_man_woman   @emoji :couplekiss_man_woman: from "couplekiss_man_woman"<br>
   @emoji couplekiss_woman_woman   @emoji :couplekiss_woman_woman: from "couplekiss_woman_woman"<br>
   @emoji credit_card   @emoji :credit_card: from "credit_card"<br>
   @emoji crescent_moon   @emoji :crescent_moon: from "crescent_moon"<br>
   @emoji cricket   @emoji :cricket: from "cricket"<br>
+  @emoji cricket_game   @emoji :cricket_game: from "cricket_game"<br>
   @emoji croatia   @emoji :croatia: from "croatia"<br>
   @emoji crocodile   @emoji :crocodile: from "crocodile"<br>
   @emoji croissant   @emoji :croissant: from "croissant"<br>
   @emoji crystal_ball   @emoji :crystal_ball: from "crystal_ball"<br>
   @emoji cuba   @emoji :cuba: from "cuba"<br>
   @emoji cucumber   @emoji :cucumber: from "cucumber"<br>
+  @emoji cup_with_straw   @emoji :cup_with_straw: from "cup_with_straw"<br>
+  @emoji cupcake   @emoji :cupcake: from "cupcake"<br>
   @emoji cupid   @emoji :cupid: from "cupid"<br>
   @emoji curacao   @emoji :curacao: from "curacao"<br>
+  @emoji curling_stone   @emoji :curling_stone: from "curling_stone"<br>
+  @emoji curly_haired_man   @emoji :curly_haired_man: from "curly_haired_man"<br>
+  @emoji curly_haired_woman   @emoji :curly_haired_woman: from "curly_haired_woman"<br>
   @emoji curly_loop   @emoji :curly_loop: from "curly_loop"<br>
   @emoji currency_exchange   @emoji :currency_exchange: from "currency_exchange"<br>
   @emoji curry   @emoji :curry: from "curry"<br>
+  @emoji cursing_face   @emoji :cursing_face: from "cursing_face"<br>
   @emoji custard   @emoji :custard: from "custard"<br>
   @emoji customs   @emoji :customs: from "customs"<br>
+  @emoji cut_of_meat   @emoji :cut_of_meat: from "cut_of_meat"<br>
   @emoji cyclone   @emoji :cyclone: from "cyclone"<br>
   @emoji cyprus   @emoji :cyprus: from "cyprus"<br>
   @emoji czech_republic   @emoji :czech_republic: from "czech_republic"<br>
   @emoji dash   @emoji :dash: from "dash"<br>
   @emoji date   @emoji :date: from "date"<br>
   @emoji de   @emoji :de: from "de"<br>
+  @emoji deaf_man   @emoji :deaf_man: from "deaf_man"<br>
+  @emoji deaf_person   @emoji :deaf_person: from "deaf_person"<br>
+  @emoji deaf_woman   @emoji :deaf_woman: from "deaf_woman"<br>
   @emoji deciduous_tree   @emoji :deciduous_tree: from "deciduous_tree"<br>
   @emoji deer   @emoji :deer: from "deer"<br>
   @emoji denmark   @emoji :denmark: from "denmark"<br>
   @emoji detective   @emoji :detective: from "detective"<br>
   @emoji diamond_shape_with_a_dot_inside   @emoji :diamond_shape_with_a_dot_inside: from "diamond_shape_with_a_dot_inside"<br>
   @emoji diamonds   @emoji :diamonds: from "diamonds"<br>
+  @emoji diego_garcia   @emoji :diego_garcia: from "diego_garcia"<br>
   @emoji disappointed   @emoji :disappointed: from "disappointed"<br>
   @emoji disappointed_relieved   @emoji :disappointed_relieved: from "disappointed_relieved"<br>
+  @emoji disguised_face   @emoji :disguised_face: from "disguised_face"<br>
+  @emoji diving_mask   @emoji :diving_mask: from "diving_mask"<br>
+  @emoji diya_lamp   @emoji :diya_lamp: from "diya_lamp"<br>
   @emoji dizzy   @emoji :dizzy: from "dizzy"<br>
   @emoji dizzy_face   @emoji :dizzy_face: from "dizzy_face"<br>
   @emoji djibouti   @emoji :djibouti: from "djibouti"<br>
+  @emoji dna   @emoji :dna: from "dna"<br>
   @emoji do_not_litter   @emoji :do_not_litter: from "do_not_litter"<br>
+  @emoji dodo   @emoji :dodo: from "dodo"<br>
   @emoji dog   @emoji :dog: from "dog"<br>
   @emoji dog2   @emoji :dog2: from "dog2"<br>
   @emoji dollar   @emoji :dollar: from "dollar"<br>
   @emoji dress   @emoji :dress: from "dress"<br>
   @emoji dromedary_camel   @emoji :dromedary_camel: from "dromedary_camel"<br>
   @emoji drooling_face   @emoji :drooling_face: from "drooling_face"<br>
+  @emoji drop_of_blood   @emoji :drop_of_blood: from "drop_of_blood"<br>
   @emoji droplet   @emoji :droplet: from "droplet"<br>
   @emoji drum   @emoji :drum: from "drum"<br>
   @emoji duck   @emoji :duck: from "duck"<br>
+  @emoji dumpling   @emoji :dumpling: from "dumpling"<br>
   @emoji dvd   @emoji :dvd: from "dvd"<br>
   @emoji e-mail   @emoji :e-mail: from "e-mail"<br>
   @emoji eagle   @emoji :eagle: from "eagle"<br>
   @emoji ear   @emoji :ear: from "ear"<br>
   @emoji ear_of_rice   @emoji :ear_of_rice: from "ear_of_rice"<br>
+  @emoji ear_with_hearing_aid   @emoji :ear_with_hearing_aid: from "ear_with_hearing_aid"<br>
   @emoji earth_africa   @emoji :earth_africa: from "earth_africa"<br>
   @emoji earth_americas   @emoji :earth_americas: from "earth_americas"<br>
   @emoji earth_asia   @emoji :earth_asia: from "earth_asia"<br>
   @emoji eight   @emoji :eight: from "eight"<br>
   @emoji eight_pointed_black_star   @emoji :eight_pointed_black_star: from "eight_pointed_black_star"<br>
   @emoji eight_spoked_asterisk   @emoji :eight_spoked_asterisk: from "eight_spoked_asterisk"<br>
+  @emoji eject_button   @emoji :eject_button: from "eject_button"<br>
   @emoji el_salvador   @emoji :el_salvador: from "el_salvador"<br>
   @emoji electric_plug   @emoji :electric_plug: from "electric_plug"<br>
   @emoji elephant   @emoji :elephant: from "elephant"<br>
+  @emoji elevator   @emoji :elevator: from "elevator"<br>
+  @emoji elf   @emoji :elf: from "elf"<br>
+  @emoji elf_man   @emoji :elf_man: from "elf_man"<br>
+  @emoji elf_woman   @emoji :elf_woman: from "elf_woman"<br>
   @emoji email   @emoji :email: from "email"<br>
   @emoji end   @emoji :end: from "end"<br>
+  @emoji england   @emoji :england: from "england"<br>
   @emoji envelope   @emoji :envelope: from "envelope"<br>
   @emoji envelope_with_arrow   @emoji :envelope_with_arrow: from "envelope_with_arrow"<br>
   @emoji equatorial_guinea   @emoji :equatorial_guinea: from "equatorial_guinea"<br>
   @emoji european_union   @emoji :european_union: from "european_union"<br>
   @emoji evergreen_tree   @emoji :evergreen_tree: from "evergreen_tree"<br>
   @emoji exclamation   @emoji :exclamation: from "exclamation"<br>
+  @emoji exploding_head   @emoji :exploding_head: from "exploding_head"<br>
   @emoji expressionless   @emoji :expressionless: from "expressionless"<br>
   @emoji eye   @emoji :eye: from "eye"<br>
   @emoji eye_speech_bubble   @emoji :eye_speech_bubble: from "eye_speech_bubble"<br>
   @emoji eyeglasses   @emoji :eyeglasses: from "eyeglasses"<br>
   @emoji eyes   @emoji :eyes: from "eyes"<br>
+  @emoji face_exhaling   @emoji :face_exhaling: from "face_exhaling"<br>
+  @emoji face_in_clouds   @emoji :face_in_clouds: from "face_in_clouds"<br>
   @emoji face_with_head_bandage   @emoji :face_with_head_bandage: from "face_with_head_bandage"<br>
+  @emoji face_with_spiral_eyes   @emoji :face_with_spiral_eyes: from "face_with_spiral_eyes"<br>
   @emoji face_with_thermometer   @emoji :face_with_thermometer: from "face_with_thermometer"<br>
+  @emoji facepalm   @emoji :facepalm: from "facepalm"<br>
   @emoji facepunch   @emoji :facepunch: from "facepunch"<br>
   @emoji factory   @emoji :factory: from "factory"<br>
+  @emoji factory_worker   @emoji :factory_worker: from "factory_worker"<br>
+  @emoji fairy   @emoji :fairy: from "fairy"<br>
+  @emoji fairy_man   @emoji :fairy_man: from "fairy_man"<br>
+  @emoji fairy_woman   @emoji :fairy_woman: from "fairy_woman"<br>
+  @emoji falafel   @emoji :falafel: from "falafel"<br>
   @emoji falkland_islands   @emoji :falkland_islands: from "falkland_islands"<br>
   @emoji fallen_leaf   @emoji :fallen_leaf: from "fallen_leaf"<br>
   @emoji family   @emoji :family: from "family"<br>
   @emoji family_woman_woman_girl   @emoji :family_woman_woman_girl: from "family_woman_woman_girl"<br>
   @emoji family_woman_woman_girl_boy   @emoji :family_woman_woman_girl_boy: from "family_woman_woman_girl_boy"<br>
   @emoji family_woman_woman_girl_girl   @emoji :family_woman_woman_girl_girl: from "family_woman_woman_girl_girl"<br>
+  @emoji farmer   @emoji :farmer: from "farmer"<br>
   @emoji faroe_islands   @emoji :faroe_islands: from "faroe_islands"<br>
   @emoji fast_forward   @emoji :fast_forward: from "fast_forward"<br>
   @emoji fax   @emoji :fax: from "fax"<br>
   @emoji fearful   @emoji :fearful: from "fearful"<br>
+  @emoji feather   @emoji :feather: from "feather"<br>
   @emoji feet   @emoji :feet: from "feet"<br>
   @emoji female_detective   @emoji :female_detective: from "female_detective"<br>
+  @emoji female_sign   @emoji :female_sign: from "female_sign"<br>
   @emoji ferris_wheel   @emoji :ferris_wheel: from "ferris_wheel"<br>
   @emoji ferry   @emoji :ferry: from "ferry"<br>
   @emoji field_hockey   @emoji :field_hockey: from "field_hockey"<br>
   @emoji finland   @emoji :finland: from "finland"<br>
   @emoji fire   @emoji :fire: from "fire"<br>
   @emoji fire_engine   @emoji :fire_engine: from "fire_engine"<br>
+  @emoji fire_extinguisher   @emoji :fire_extinguisher: from "fire_extinguisher"<br>
+  @emoji firecracker   @emoji :firecracker: from "firecracker"<br>
+  @emoji firefighter   @emoji :firefighter: from "firefighter"<br>
   @emoji fireworks   @emoji :fireworks: from "fireworks"<br>
   @emoji first_quarter_moon   @emoji :first_quarter_moon: from "first_quarter_moon"<br>
   @emoji first_quarter_moon_with_face   @emoji :first_quarter_moon_with_face: from "first_quarter_moon_with_face"<br>
   @emoji fist_right   @emoji :fist_right: from "fist_right"<br>
   @emoji five   @emoji :five: from "five"<br>
   @emoji flags   @emoji :flags: from "flags"<br>
+  @emoji flamingo   @emoji :flamingo: from "flamingo"<br>
   @emoji flashlight   @emoji :flashlight: from "flashlight"<br>
+  @emoji flat_shoe   @emoji :flat_shoe: from "flat_shoe"<br>
+  @emoji flatbread   @emoji :flatbread: from "flatbread"<br>
   @emoji fleur_de_lis   @emoji :fleur_de_lis: from "fleur_de_lis"<br>
   @emoji flight_arrival   @emoji :flight_arrival: from "flight_arrival"<br>
   @emoji flight_departure   @emoji :flight_departure: from "flight_departure"<br>
   @emoji floppy_disk   @emoji :floppy_disk: from "floppy_disk"<br>
   @emoji flower_playing_cards   @emoji :flower_playing_cards: from "flower_playing_cards"<br>
   @emoji flushed   @emoji :flushed: from "flushed"<br>
+  @emoji fly   @emoji :fly: from "fly"<br>
+  @emoji flying_disc   @emoji :flying_disc: from "flying_disc"<br>
+  @emoji flying_saucer   @emoji :flying_saucer: from "flying_saucer"<br>
   @emoji fog   @emoji :fog: from "fog"<br>
   @emoji foggy   @emoji :foggy: from "foggy"<br>
+  @emoji fondue   @emoji :fondue: from "fondue"<br>
+  @emoji foot   @emoji :foot: from "foot"<br>
   @emoji football   @emoji :football: from "football"<br>
   @emoji footprints   @emoji :footprints: from "footprints"<br>
   @emoji fork_and_knife   @emoji :fork_and_knife: from "fork_and_knife"<br>
+  @emoji fortune_cookie   @emoji :fortune_cookie: from "fortune_cookie"<br>
   @emoji fountain   @emoji :fountain: from "fountain"<br>
   @emoji fountain_pen   @emoji :fountain_pen: from "fountain_pen"<br>
   @emoji four   @emoji :four: from "four"<br>
   @emoji frowning   @emoji :frowning: from "frowning"<br>
   @emoji frowning_face   @emoji :frowning_face: from "frowning_face"<br>
   @emoji frowning_man   @emoji :frowning_man: from "frowning_man"<br>
+  @emoji frowning_person   @emoji :frowning_person: from "frowning_person"<br>
   @emoji frowning_woman   @emoji :frowning_woman: from "frowning_woman"<br>
   @emoji fu   @emoji :fu: from "fu"<br>
   @emoji fuelpump   @emoji :fuelpump: from "fuelpump"<br>
   @emoji gabon   @emoji :gabon: from "gabon"<br>
   @emoji gambia   @emoji :gambia: from "gambia"<br>
   @emoji game_die   @emoji :game_die: from "game_die"<br>
+  @emoji garlic   @emoji :garlic: from "garlic"<br>
   @emoji gb   @emoji :gb: from "gb"<br>
   @emoji gear   @emoji :gear: from "gear"<br>
   @emoji gem   @emoji :gem: from "gem"<br>
   @emoji gemini   @emoji :gemini: from "gemini"<br>
+  @emoji genie   @emoji :genie: from "genie"<br>
+  @emoji genie_man   @emoji :genie_man: from "genie_man"<br>
+  @emoji genie_woman   @emoji :genie_woman: from "genie_woman"<br>
   @emoji georgia   @emoji :georgia: from "georgia"<br>
   @emoji ghana   @emoji :ghana: from "ghana"<br>
   @emoji ghost   @emoji :ghost: from "ghost"<br>
   @emoji gibraltar   @emoji :gibraltar: from "gibraltar"<br>
   @emoji gift   @emoji :gift: from "gift"<br>
   @emoji gift_heart   @emoji :gift_heart: from "gift_heart"<br>
+  @emoji giraffe   @emoji :giraffe: from "giraffe"<br>
   @emoji girl   @emoji :girl: from "girl"<br>
   @emoji globe_with_meridians   @emoji :globe_with_meridians: from "globe_with_meridians"<br>
+  @emoji gloves   @emoji :gloves: from "gloves"<br>
   @emoji goal_net   @emoji :goal_net: from "goal_net"<br>
   @emoji goat   @emoji :goat: from "goat"<br>
+  @emoji goggles   @emoji :goggles: from "goggles"<br>
   @emoji golf   @emoji :golf: from "golf"<br>
+  @emoji golfing   @emoji :golfing: from "golfing"<br>
   @emoji golfing_man   @emoji :golfing_man: from "golfing_man"<br>
   @emoji golfing_woman   @emoji :golfing_woman: from "golfing_woman"<br>
   @emoji gorilla   @emoji :gorilla: from "gorilla"<br>
   @emoji greece   @emoji :greece: from "greece"<br>
   @emoji green_apple   @emoji :green_apple: from "green_apple"<br>
   @emoji green_book   @emoji :green_book: from "green_book"<br>
+  @emoji green_circle   @emoji :green_circle: from "green_circle"<br>
   @emoji green_heart   @emoji :green_heart: from "green_heart"<br>
   @emoji green_salad   @emoji :green_salad: from "green_salad"<br>
+  @emoji green_square   @emoji :green_square: from "green_square"<br>
   @emoji greenland   @emoji :greenland: from "greenland"<br>
   @emoji grenada   @emoji :grenada: from "grenada"<br>
   @emoji grey_exclamation   @emoji :grey_exclamation: from "grey_exclamation"<br>
   @emoji grinning   @emoji :grinning: from "grinning"<br>
   @emoji guadeloupe   @emoji :guadeloupe: from "guadeloupe"<br>
   @emoji guam   @emoji :guam: from "guam"<br>
+  @emoji guard   @emoji :guard: from "guard"<br>
   @emoji guardsman   @emoji :guardsman: from "guardsman"<br>
   @emoji guardswoman   @emoji :guardswoman: from "guardswoman"<br>
   @emoji guatemala   @emoji :guatemala: from "guatemala"<br>
   @emoji guernsey   @emoji :guernsey: from "guernsey"<br>
+  @emoji guide_dog   @emoji :guide_dog: from "guide_dog"<br>
   @emoji guinea   @emoji :guinea: from "guinea"<br>
   @emoji guinea_bissau   @emoji :guinea_bissau: from "guinea_bissau"<br>
   @emoji guitar   @emoji :guitar: from "guitar"<br>
   @emoji hammer_and_wrench   @emoji :hammer_and_wrench: from "hammer_and_wrench"<br>
   @emoji hamster   @emoji :hamster: from "hamster"<br>
   @emoji hand   @emoji :hand: from "hand"<br>
+  @emoji hand_over_mouth   @emoji :hand_over_mouth: from "hand_over_mouth"<br>
   @emoji handbag   @emoji :handbag: from "handbag"<br>
+  @emoji handball_person   @emoji :handball_person: from "handball_person"<br>
   @emoji handshake   @emoji :handshake: from "handshake"<br>
   @emoji hankey   @emoji :hankey: from "hankey"<br>
   @emoji hash   @emoji :hash: from "hash"<br>
   @emoji hatched_chick   @emoji :hatched_chick: from "hatched_chick"<br>
   @emoji hatching_chick   @emoji :hatching_chick: from "hatching_chick"<br>
   @emoji headphones   @emoji :headphones: from "headphones"<br>
+  @emoji headstone   @emoji :headstone: from "headstone"<br>
+  @emoji health_worker   @emoji :health_worker: from "health_worker"<br>
   @emoji hear_no_evil   @emoji :hear_no_evil: from "hear_no_evil"<br>
+  @emoji heard_mcdonald_islands   @emoji :heard_mcdonald_islands: from "heard_mcdonald_islands"<br>
   @emoji heart   @emoji :heart: from "heart"<br>
   @emoji heart_decoration   @emoji :heart_decoration: from "heart_decoration"<br>
   @emoji heart_eyes   @emoji :heart_eyes: from "heart_eyes"<br>
   @emoji heart_eyes_cat   @emoji :heart_eyes_cat: from "heart_eyes_cat"<br>
+  @emoji heart_on_fire   @emoji :heart_on_fire: from "heart_on_fire"<br>
   @emoji heartbeat   @emoji :heartbeat: from "heartbeat"<br>
   @emoji heartpulse   @emoji :heartpulse: from "heartpulse"<br>
   @emoji hearts   @emoji :hearts: from "hearts"<br>
   @emoji heavy_minus_sign   @emoji :heavy_minus_sign: from "heavy_minus_sign"<br>
   @emoji heavy_multiplication_x   @emoji :heavy_multiplication_x: from "heavy_multiplication_x"<br>
   @emoji heavy_plus_sign   @emoji :heavy_plus_sign: from "heavy_plus_sign"<br>
+  @emoji hedgehog   @emoji :hedgehog: from "hedgehog"<br>
   @emoji helicopter   @emoji :helicopter: from "helicopter"<br>
   @emoji herb   @emoji :herb: from "herb"<br>
   @emoji hibiscus   @emoji :hibiscus: from "hibiscus"<br>
   @emoji high_brightness   @emoji :high_brightness: from "high_brightness"<br>
   @emoji high_heel   @emoji :high_heel: from "high_heel"<br>
+  @emoji hiking_boot   @emoji :hiking_boot: from "hiking_boot"<br>
+  @emoji hindu_temple   @emoji :hindu_temple: from "hindu_temple"<br>
+  @emoji hippopotamus   @emoji :hippopotamus: from "hippopotamus"<br>
   @emoji hocho   @emoji :hocho: from "hocho"<br>
   @emoji hole   @emoji :hole: from "hole"<br>
   @emoji honduras   @emoji :honduras: from "honduras"<br>
   @emoji honey_pot   @emoji :honey_pot: from "honey_pot"<br>
   @emoji honeybee   @emoji :honeybee: from "honeybee"<br>
   @emoji hong_kong   @emoji :hong_kong: from "hong_kong"<br>
+  @emoji hook   @emoji :hook: from "hook"<br>
   @emoji horse   @emoji :horse: from "horse"<br>
   @emoji horse_racing   @emoji :horse_racing: from "horse_racing"<br>
   @emoji hospital   @emoji :hospital: from "hospital"<br>
+  @emoji hot_face   @emoji :hot_face: from "hot_face"<br>
   @emoji hot_pepper   @emoji :hot_pepper: from "hot_pepper"<br>
   @emoji hotdog   @emoji :hotdog: from "hotdog"<br>
   @emoji hotel   @emoji :hotel: from "hotel"<br>
   @emoji hugs   @emoji :hugs: from "hugs"<br>
   @emoji hungary   @emoji :hungary: from "hungary"<br>
   @emoji hushed   @emoji :hushed: from "hushed"<br>
+  @emoji hut   @emoji :hut: from "hut"<br>
   @emoji ice_cream   @emoji :ice_cream: from "ice_cream"<br>
+  @emoji ice_cube   @emoji :ice_cube: from "ice_cube"<br>
   @emoji ice_hockey   @emoji :ice_hockey: from "ice_hockey"<br>
   @emoji ice_skate   @emoji :ice_skate: from "ice_skate"<br>
   @emoji icecream   @emoji :icecream: from "icecream"<br>
   @emoji incoming_envelope   @emoji :incoming_envelope: from "incoming_envelope"<br>
   @emoji india   @emoji :india: from "india"<br>
   @emoji indonesia   @emoji :indonesia: from "indonesia"<br>
+  @emoji infinity   @emoji :infinity: from "infinity"<br>
   @emoji information_desk_person   @emoji :information_desk_person: from "information_desk_person"<br>
   @emoji information_source   @emoji :information_source: from "information_source"<br>
   @emoji innocent   @emoji :innocent: from "innocent"<br>
   @emoji japanese_ogre   @emoji :japanese_ogre: from "japanese_ogre"<br>
   @emoji jeans   @emoji :jeans: from "jeans"<br>
   @emoji jersey   @emoji :jersey: from "jersey"<br>
+  @emoji jigsaw   @emoji :jigsaw: from "jigsaw"<br>
   @emoji jordan   @emoji :jordan: from "jordan"<br>
   @emoji joy   @emoji :joy: from "joy"<br>
   @emoji joy_cat   @emoji :joy_cat: from "joy_cat"<br>
   @emoji joystick   @emoji :joystick: from "joystick"<br>
   @emoji jp   @emoji :jp: from "jp"<br>
+  @emoji judge   @emoji :judge: from "judge"<br>
+  @emoji juggling_person   @emoji :juggling_person: from "juggling_person"<br>
   @emoji kaaba   @emoji :kaaba: from "kaaba"<br>
+  @emoji kangaroo   @emoji :kangaroo: from "kangaroo"<br>
   @emoji kazakhstan   @emoji :kazakhstan: from "kazakhstan"<br>
   @emoji kenya   @emoji :kenya: from "kenya"<br>
   @emoji key   @emoji :key: from "key"<br>
   @emoji kissing_closed_eyes   @emoji :kissing_closed_eyes: from "kissing_closed_eyes"<br>
   @emoji kissing_heart   @emoji :kissing_heart: from "kissing_heart"<br>
   @emoji kissing_smiling_eyes   @emoji :kissing_smiling_eyes: from "kissing_smiling_eyes"<br>
+  @emoji kite   @emoji :kite: from "kite"<br>
   @emoji kiwi_fruit   @emoji :kiwi_fruit: from "kiwi_fruit"<br>
+  @emoji kneeling_man   @emoji :kneeling_man: from "kneeling_man"<br>
+  @emoji kneeling_person   @emoji :kneeling_person: from "kneeling_person"<br>
+  @emoji kneeling_woman   @emoji :kneeling_woman: from "kneeling_woman"<br>
   @emoji knife   @emoji :knife: from "knife"<br>
+  @emoji knot   @emoji :knot: from "knot"<br>
   @emoji koala   @emoji :koala: from "koala"<br>
   @emoji koko   @emoji :koko: from "koko"<br>
   @emoji kosovo   @emoji :kosovo: from "kosovo"<br>
   @emoji kr   @emoji :kr: from "kr"<br>
   @emoji kuwait   @emoji :kuwait: from "kuwait"<br>
   @emoji kyrgyzstan   @emoji :kyrgyzstan: from "kyrgyzstan"<br>
+  @emoji lab_coat   @emoji :lab_coat: from "lab_coat"<br>
   @emoji label   @emoji :label: from "label"<br>
+  @emoji lacrosse   @emoji :lacrosse: from "lacrosse"<br>
+  @emoji ladder   @emoji :ladder: from "ladder"<br>
+  @emoji lady_beetle   @emoji :lady_beetle: from "lady_beetle"<br>
   @emoji lantern   @emoji :lantern: from "lantern"<br>
   @emoji laos   @emoji :laos: from "laos"<br>
   @emoji large_blue_circle   @emoji :large_blue_circle: from "large_blue_circle"<br>
   @emoji latin_cross   @emoji :latin_cross: from "latin_cross"<br>
   @emoji latvia   @emoji :latvia: from "latvia"<br>
   @emoji laughing   @emoji :laughing: from "laughing"<br>
+  @emoji leafy_green   @emoji :leafy_green: from "leafy_green"<br>
   @emoji leaves   @emoji :leaves: from "leaves"<br>
   @emoji lebanon   @emoji :lebanon: from "lebanon"<br>
   @emoji ledger   @emoji :ledger: from "ledger"<br>
   @emoji left_luggage   @emoji :left_luggage: from "left_luggage"<br>
   @emoji left_right_arrow   @emoji :left_right_arrow: from "left_right_arrow"<br>
+  @emoji left_speech_bubble   @emoji :left_speech_bubble: from "left_speech_bubble"<br>
   @emoji leftwards_arrow_with_hook   @emoji :leftwards_arrow_with_hook: from "leftwards_arrow_with_hook"<br>
+  @emoji leg   @emoji :leg: from "leg"<br>
   @emoji lemon   @emoji :lemon: from "lemon"<br>
   @emoji leo   @emoji :leo: from "leo"<br>
   @emoji leopard   @emoji :leopard: from "leopard"<br>
   @emoji lipstick   @emoji :lipstick: from "lipstick"<br>
   @emoji lithuania   @emoji :lithuania: from "lithuania"<br>
   @emoji lizard   @emoji :lizard: from "lizard"<br>
+  @emoji llama   @emoji :llama: from "llama"<br>
+  @emoji lobster   @emoji :lobster: from "lobster"<br>
   @emoji lock   @emoji :lock: from "lock"<br>
   @emoji lock_with_ink_pen   @emoji :lock_with_ink_pen: from "lock_with_ink_pen"<br>
   @emoji lollipop   @emoji :lollipop: from "lollipop"<br>
+  @emoji long_drum   @emoji :long_drum: from "long_drum"<br>
   @emoji loop   @emoji :loop: from "loop"<br>
+  @emoji lotion_bottle   @emoji :lotion_bottle: from "lotion_bottle"<br>
+  @emoji lotus_position   @emoji :lotus_position: from "lotus_position"<br>
+  @emoji lotus_position_man   @emoji :lotus_position_man: from "lotus_position_man"<br>
+  @emoji lotus_position_woman   @emoji :lotus_position_woman: from "lotus_position_woman"<br>
   @emoji loud_sound   @emoji :loud_sound: from "loud_sound"<br>
   @emoji loudspeaker   @emoji :loudspeaker: from "loudspeaker"<br>
   @emoji love_hotel   @emoji :love_hotel: from "love_hotel"<br>
   @emoji love_letter   @emoji :love_letter: from "love_letter"<br>
+  @emoji love_you_gesture   @emoji :love_you_gesture: from "love_you_gesture"<br>
   @emoji low_brightness   @emoji :low_brightness: from "low_brightness"<br>
+  @emoji luggage   @emoji :luggage: from "luggage"<br>
+  @emoji lungs   @emoji :lungs: from "lungs"<br>
   @emoji luxembourg   @emoji :luxembourg: from "luxembourg"<br>
   @emoji lying_face   @emoji :lying_face: from "lying_face"<br>
   @emoji m   @emoji :m: from "m"<br>
   @emoji madagascar   @emoji :madagascar: from "madagascar"<br>
   @emoji mag   @emoji :mag: from "mag"<br>
   @emoji mag_right   @emoji :mag_right: from "mag_right"<br>
+  @emoji mage   @emoji :mage: from "mage"<br>
+  @emoji mage_man   @emoji :mage_man: from "mage_man"<br>
+  @emoji mage_woman   @emoji :mage_woman: from "mage_woman"<br>
+  @emoji magic_wand   @emoji :magic_wand: from "magic_wand"<br>
+  @emoji magnet   @emoji :magnet: from "magnet"<br>
   @emoji mahjong   @emoji :mahjong: from "mahjong"<br>
   @emoji mailbox   @emoji :mailbox: from "mailbox"<br>
   @emoji mailbox_closed   @emoji :mailbox_closed: from "mailbox_closed"<br>
   @emoji malaysia   @emoji :malaysia: from "malaysia"<br>
   @emoji maldives   @emoji :maldives: from "maldives"<br>
   @emoji male_detective   @emoji :male_detective: from "male_detective"<br>
+  @emoji male_sign   @emoji :male_sign: from "male_sign"<br>
   @emoji mali   @emoji :mali: from "mali"<br>
   @emoji malta   @emoji :malta: from "malta"<br>
+  @emoji mammoth   @emoji :mammoth: from "mammoth"<br>
   @emoji man   @emoji :man: from "man"<br>
   @emoji man_artist   @emoji :man_artist: from "man_artist"<br>
   @emoji man_astronaut   @emoji :man_astronaut: from "man_astronaut"<br>
+  @emoji man_beard   @emoji :man_beard: from "man_beard"<br>
   @emoji man_cartwheeling   @emoji :man_cartwheeling: from "man_cartwheeling"<br>
   @emoji man_cook   @emoji :man_cook: from "man_cook"<br>
   @emoji man_dancing   @emoji :man_dancing: from "man_dancing"<br>
   @emoji man_facepalming   @emoji :man_facepalming: from "man_facepalming"<br>
   @emoji man_factory_worker   @emoji :man_factory_worker: from "man_factory_worker"<br>
   @emoji man_farmer   @emoji :man_farmer: from "man_farmer"<br>
+  @emoji man_feeding_baby   @emoji :man_feeding_baby: from "man_feeding_baby"<br>
   @emoji man_firefighter   @emoji :man_firefighter: from "man_firefighter"<br>
   @emoji man_health_worker   @emoji :man_health_worker: from "man_health_worker"<br>
+  @emoji man_in_manual_wheelchair   @emoji :man_in_manual_wheelchair: from "man_in_manual_wheelchair"<br>
+  @emoji man_in_motorized_wheelchair   @emoji :man_in_motorized_wheelchair: from "man_in_motorized_wheelchair"<br>
   @emoji man_in_tuxedo   @emoji :man_in_tuxedo: from "man_in_tuxedo"<br>
   @emoji man_judge   @emoji :man_judge: from "man_judge"<br>
   @emoji man_juggling   @emoji :man_juggling: from "man_juggling"<br>
   @emoji man_teacher   @emoji :man_teacher: from "man_teacher"<br>
   @emoji man_technologist   @emoji :man_technologist: from "man_technologist"<br>
   @emoji man_with_gua_pi_mao   @emoji :man_with_gua_pi_mao: from "man_with_gua_pi_mao"<br>
+  @emoji man_with_probing_cane   @emoji :man_with_probing_cane: from "man_with_probing_cane"<br>
   @emoji man_with_turban   @emoji :man_with_turban: from "man_with_turban"<br>
+  @emoji man_with_veil   @emoji :man_with_veil: from "man_with_veil"<br>
   @emoji mandarin   @emoji :mandarin: from "mandarin"<br>
+  @emoji mango   @emoji :mango: from "mango"<br>
   @emoji mans_shoe   @emoji :mans_shoe: from "mans_shoe"<br>
   @emoji mantelpiece_clock   @emoji :mantelpiece_clock: from "mantelpiece_clock"<br>
+  @emoji manual_wheelchair   @emoji :manual_wheelchair: from "manual_wheelchair"<br>
   @emoji maple_leaf   @emoji :maple_leaf: from "maple_leaf"<br>
   @emoji marshall_islands   @emoji :marshall_islands: from "marshall_islands"<br>
   @emoji martial_arts_uniform   @emoji :martial_arts_uniform: from "martial_arts_uniform"<br>
   @emoji massage   @emoji :massage: from "massage"<br>
   @emoji massage_man   @emoji :massage_man: from "massage_man"<br>
   @emoji massage_woman   @emoji :massage_woman: from "massage_woman"<br>
+  @emoji mate   @emoji :mate: from "mate"<br>
   @emoji mauritania   @emoji :mauritania: from "mauritania"<br>
   @emoji mauritius   @emoji :mauritius: from "mauritius"<br>
   @emoji mayotte   @emoji :mayotte: from "mayotte"<br>
   @emoji meat_on_bone   @emoji :meat_on_bone: from "meat_on_bone"<br>
+  @emoji mechanic   @emoji :mechanic: from "mechanic"<br>
+  @emoji mechanical_arm   @emoji :mechanical_arm: from "mechanical_arm"<br>
+  @emoji mechanical_leg   @emoji :mechanical_leg: from "mechanical_leg"<br>
   @emoji medal_military   @emoji :medal_military: from "medal_military"<br>
   @emoji medal_sports   @emoji :medal_sports: from "medal_sports"<br>
+  @emoji medical_symbol   @emoji :medical_symbol: from "medical_symbol"<br>
   @emoji mega   @emoji :mega: from "mega"<br>
   @emoji melon   @emoji :melon: from "melon"<br>
   @emoji memo   @emoji :memo: from "memo"<br>
   @emoji men_wrestling   @emoji :men_wrestling: from "men_wrestling"<br>
+  @emoji mending_heart   @emoji :mending_heart: from "mending_heart"<br>
   @emoji menorah   @emoji :menorah: from "menorah"<br>
   @emoji mens   @emoji :mens: from "mens"<br>
+  @emoji mermaid   @emoji :mermaid: from "mermaid"<br>
+  @emoji merman   @emoji :merman: from "merman"<br>
+  @emoji merperson   @emoji :merperson: from "merperson"<br>
   @emoji metal   @emoji :metal: from "metal"<br>
   @emoji metro   @emoji :metro: from "metro"<br>
   @emoji mexico   @emoji :mexico: from "mexico"<br>
+  @emoji microbe   @emoji :microbe: from "microbe"<br>
   @emoji micronesia   @emoji :micronesia: from "micronesia"<br>
   @emoji microphone   @emoji :microphone: from "microphone"<br>
   @emoji microscope   @emoji :microscope: from "microscope"<br>
   @emoji middle_finger   @emoji :middle_finger: from "middle_finger"<br>
+  @emoji military_helmet   @emoji :military_helmet: from "military_helmet"<br>
   @emoji milk_glass   @emoji :milk_glass: from "milk_glass"<br>
   @emoji milky_way   @emoji :milky_way: from "milky_way"<br>
   @emoji minibus   @emoji :minibus: from "minibus"<br>
   @emoji minidisc   @emoji :minidisc: from "minidisc"<br>
+  @emoji mirror   @emoji :mirror: from "mirror"<br>
   @emoji mobile_phone_off   @emoji :mobile_phone_off: from "mobile_phone_off"<br>
   @emoji moldova   @emoji :moldova: from "moldova"<br>
   @emoji monaco   @emoji :monaco: from "monaco"<br>
   @emoji mongolia   @emoji :mongolia: from "mongolia"<br>
   @emoji monkey   @emoji :monkey: from "monkey"<br>
   @emoji monkey_face   @emoji :monkey_face: from "monkey_face"<br>
+  @emoji monocle_face   @emoji :monocle_face: from "monocle_face"<br>
   @emoji monorail   @emoji :monorail: from "monorail"<br>
   @emoji montenegro   @emoji :montenegro: from "montenegro"<br>
   @emoji montserrat   @emoji :montserrat: from "montserrat"<br>
   @emoji moon   @emoji :moon: from "moon"<br>
+  @emoji moon_cake   @emoji :moon_cake: from "moon_cake"<br>
   @emoji morocco   @emoji :morocco: from "morocco"<br>
   @emoji mortar_board   @emoji :mortar_board: from "mortar_board"<br>
   @emoji mosque   @emoji :mosque: from "mosque"<br>
+  @emoji mosquito   @emoji :mosquito: from "mosquito"<br>
   @emoji motor_boat   @emoji :motor_boat: from "motor_boat"<br>
   @emoji motor_scooter   @emoji :motor_scooter: from "motor_scooter"<br>
   @emoji motorcycle   @emoji :motorcycle: from "motorcycle"<br>
+  @emoji motorized_wheelchair   @emoji :motorized_wheelchair: from "motorized_wheelchair"<br>
   @emoji motorway   @emoji :motorway: from "motorway"<br>
   @emoji mount_fuji   @emoji :mount_fuji: from "mount_fuji"<br>
   @emoji mountain   @emoji :mountain: from "mountain"<br>
   @emoji mountain_snow   @emoji :mountain_snow: from "mountain_snow"<br>
   @emoji mouse   @emoji :mouse: from "mouse"<br>
   @emoji mouse2   @emoji :mouse2: from "mouse2"<br>
+  @emoji mouse_trap   @emoji :mouse_trap: from "mouse_trap"<br>
   @emoji movie_camera   @emoji :movie_camera: from "movie_camera"<br>
   @emoji moyai   @emoji :moyai: from "moyai"<br>
   @emoji mozambique   @emoji :mozambique: from "mozambique"<br>
   @emoji musical_note   @emoji :musical_note: from "musical_note"<br>
   @emoji musical_score   @emoji :musical_score: from "musical_score"<br>
   @emoji mute   @emoji :mute: from "mute"<br>
+  @emoji mx_claus   @emoji :mx_claus: from "mx_claus"<br>
   @emoji myanmar   @emoji :myanmar: from "myanmar"<br>
   @emoji nail_care   @emoji :nail_care: from "nail_care"<br>
   @emoji name_badge   @emoji :name_badge: from "name_badge"<br>
   @emoji national_park   @emoji :national_park: from "national_park"<br>
   @emoji nauru   @emoji :nauru: from "nauru"<br>
   @emoji nauseated_face   @emoji :nauseated_face: from "nauseated_face"<br>
+  @emoji nazar_amulet   @emoji :nazar_amulet: from "nazar_amulet"<br>
   @emoji necktie   @emoji :necktie: from "necktie"<br>
   @emoji negative_squared_cross_mark   @emoji :negative_squared_cross_mark: from "negative_squared_cross_mark"<br>
   @emoji nepal   @emoji :nepal: from "nepal"<br>
   @emoji nerd_face   @emoji :nerd_face: from "nerd_face"<br>
+  @emoji nesting_dolls   @emoji :nesting_dolls: from "nesting_dolls"<br>
   @emoji netherlands   @emoji :netherlands: from "netherlands"<br>
   @emoji neutral_face   @emoji :neutral_face: from "neutral_face"<br>
   @emoji new   @emoji :new: from "new"<br>
   @emoji nigeria   @emoji :nigeria: from "nigeria"<br>
   @emoji night_with_stars   @emoji :night_with_stars: from "night_with_stars"<br>
   @emoji nine   @emoji :nine: from "nine"<br>
+  @emoji ninja   @emoji :ninja: from "ninja"<br>
   @emoji niue   @emoji :niue: from "niue"<br>
   @emoji no_bell   @emoji :no_bell: from "no_bell"<br>
   @emoji no_bicycles   @emoji :no_bicycles: from "no_bicycles"<br>
   @emoji octopus   @emoji :octopus: from "octopus"<br>
   @emoji oden   @emoji :oden: from "oden"<br>
   @emoji office   @emoji :office: from "office"<br>
+  @emoji office_worker   @emoji :office_worker: from "office_worker"<br>
   @emoji oil_drum   @emoji :oil_drum: from "oil_drum"<br>
   @emoji ok   @emoji :ok: from "ok"<br>
   @emoji ok_hand   @emoji :ok_hand: from "ok_hand"<br>
   @emoji ok_man   @emoji :ok_man: from "ok_man"<br>
+  @emoji ok_person   @emoji :ok_person: from "ok_person"<br>
   @emoji ok_woman   @emoji :ok_woman: from "ok_woman"<br>
   @emoji old_key   @emoji :old_key: from "old_key"<br>
+  @emoji older_adult   @emoji :older_adult: from "older_adult"<br>
   @emoji older_man   @emoji :older_man: from "older_man"<br>
   @emoji older_woman   @emoji :older_woman: from "older_woman"<br>
+  @emoji olive   @emoji :olive: from "olive"<br>
   @emoji om   @emoji :om: from "om"<br>
   @emoji oman   @emoji :oman: from "oman"<br>
   @emoji on   @emoji :on: from "on"<br>
   @emoji oncoming_police_car   @emoji :oncoming_police_car: from "oncoming_police_car"<br>
   @emoji oncoming_taxi   @emoji :oncoming_taxi: from "oncoming_taxi"<br>
   @emoji one   @emoji :one: from "one"<br>
+  @emoji one_piece_swimsuit   @emoji :one_piece_swimsuit: from "one_piece_swimsuit"<br>
+  @emoji onion   @emoji :onion: from "onion"<br>
   @emoji open_book   @emoji :open_book: from "open_book"<br>
   @emoji open_file_folder   @emoji :open_file_folder: from "open_file_folder"<br>
   @emoji open_hands   @emoji :open_hands: from "open_hands"<br>
   @emoji ophiuchus   @emoji :ophiuchus: from "ophiuchus"<br>
   @emoji orange   @emoji :orange: from "orange"<br>
   @emoji orange_book   @emoji :orange_book: from "orange_book"<br>
+  @emoji orange_circle   @emoji :orange_circle: from "orange_circle"<br>
+  @emoji orange_heart   @emoji :orange_heart: from "orange_heart"<br>
+  @emoji orange_square   @emoji :orange_square: from "orange_square"<br>
+  @emoji orangutan   @emoji :orangutan: from "orangutan"<br>
   @emoji orthodox_cross   @emoji :orthodox_cross: from "orthodox_cross"<br>
+  @emoji otter   @emoji :otter: from "otter"<br>
   @emoji outbox_tray   @emoji :outbox_tray: from "outbox_tray"<br>
   @emoji owl   @emoji :owl: from "owl"<br>
   @emoji ox   @emoji :ox: from "ox"<br>
+  @emoji oyster   @emoji :oyster: from "oyster"<br>
   @emoji package   @emoji :package: from "package"<br>
   @emoji page_facing_up   @emoji :page_facing_up: from "page_facing_up"<br>
   @emoji page_with_curl   @emoji :page_with_curl: from "page_with_curl"<br>
   @emoji palau   @emoji :palau: from "palau"<br>
   @emoji palestinian_territories   @emoji :palestinian_territories: from "palestinian_territories"<br>
   @emoji palm_tree   @emoji :palm_tree: from "palm_tree"<br>
+  @emoji palms_up_together   @emoji :palms_up_together: from "palms_up_together"<br>
   @emoji panama   @emoji :panama: from "panama"<br>
   @emoji pancakes   @emoji :pancakes: from "pancakes"<br>
   @emoji panda_face   @emoji :panda_face: from "panda_face"<br>
   @emoji paperclip   @emoji :paperclip: from "paperclip"<br>
   @emoji paperclips   @emoji :paperclips: from "paperclips"<br>
   @emoji papua_new_guinea   @emoji :papua_new_guinea: from "papua_new_guinea"<br>
+  @emoji parachute   @emoji :parachute: from "parachute"<br>
   @emoji paraguay   @emoji :paraguay: from "paraguay"<br>
   @emoji parasol_on_ground   @emoji :parasol_on_ground: from "parasol_on_ground"<br>
   @emoji parking   @emoji :parking: from "parking"<br>
+  @emoji parrot   @emoji :parrot: from "parrot"<br>
   @emoji part_alternation_mark   @emoji :part_alternation_mark: from "part_alternation_mark"<br>
   @emoji partly_sunny   @emoji :partly_sunny: from "partly_sunny"<br>
+  @emoji partying_face   @emoji :partying_face: from "partying_face"<br>
   @emoji passenger_ship   @emoji :passenger_ship: from "passenger_ship"<br>
   @emoji passport_control   @emoji :passport_control: from "passport_control"<br>
   @emoji pause_button   @emoji :pause_button: from "pause_button"<br>
   @emoji paw_prints   @emoji :paw_prints: from "paw_prints"<br>
   @emoji peace_symbol   @emoji :peace_symbol: from "peace_symbol"<br>
   @emoji peach   @emoji :peach: from "peach"<br>
+  @emoji peacock   @emoji :peacock: from "peacock"<br>
   @emoji peanuts   @emoji :peanuts: from "peanuts"<br>
   @emoji pear   @emoji :pear: from "pear"<br>
   @emoji pen   @emoji :pen: from "pen"<br>
   @emoji pencil2   @emoji :pencil2: from "pencil2"<br>
   @emoji penguin   @emoji :penguin: from "penguin"<br>
   @emoji pensive   @emoji :pensive: from "pensive"<br>
+  @emoji people_holding_hands   @emoji :people_holding_hands: from "people_holding_hands"<br>
+  @emoji people_hugging   @emoji :people_hugging: from "people_hugging"<br>
   @emoji performing_arts   @emoji :performing_arts: from "performing_arts"<br>
   @emoji persevere   @emoji :persevere: from "persevere"<br>
+  @emoji person_bald   @emoji :person_bald: from "person_bald"<br>
+  @emoji person_curly_hair   @emoji :person_curly_hair: from "person_curly_hair"<br>
+  @emoji person_feeding_baby   @emoji :person_feeding_baby: from "person_feeding_baby"<br>
   @emoji person_fencing   @emoji :person_fencing: from "person_fencing"<br>
-  @emoji person_frowning   @emoji :person_frowning: from "person_frowning"<br>
-  @emoji person_with_blond_hair   @emoji :person_with_blond_hair: from "person_with_blond_hair"<br>
-  @emoji person_with_pouting_face   @emoji :person_with_pouting_face: from "person_with_pouting_face"<br>
+  @emoji person_in_manual_wheelchair   @emoji :person_in_manual_wheelchair: from "person_in_manual_wheelchair"<br>
+  @emoji person_in_motorized_wheelchair   @emoji :person_in_motorized_wheelchair: from "person_in_motorized_wheelchair"<br>
+  @emoji person_in_tuxedo   @emoji :person_in_tuxedo: from "person_in_tuxedo"<br>
+  @emoji person_red_hair   @emoji :person_red_hair: from "person_red_hair"<br>
+  @emoji person_white_hair   @emoji :person_white_hair: from "person_white_hair"<br>
+  @emoji person_with_probing_cane   @emoji :person_with_probing_cane: from "person_with_probing_cane"<br>
+  @emoji person_with_turban   @emoji :person_with_turban: from "person_with_turban"<br>
+  @emoji person_with_veil   @emoji :person_with_veil: from "person_with_veil"<br>
   @emoji peru   @emoji :peru: from "peru"<br>
+  @emoji petri_dish   @emoji :petri_dish: from "petri_dish"<br>
   @emoji philippines   @emoji :philippines: from "philippines"<br>
   @emoji phone   @emoji :phone: from "phone"<br>
   @emoji pick   @emoji :pick: from "pick"<br>
+  @emoji pickup_truck   @emoji :pickup_truck: from "pickup_truck"<br>
+  @emoji pie   @emoji :pie: from "pie"<br>
   @emoji pig   @emoji :pig: from "pig"<br>
   @emoji pig2   @emoji :pig2: from "pig2"<br>
   @emoji pig_nose   @emoji :pig_nose: from "pig_nose"<br>
   @emoji pill   @emoji :pill: from "pill"<br>
+  @emoji pilot   @emoji :pilot: from "pilot"<br>
+  @emoji pinata   @emoji :pinata: from "pinata"<br>
+  @emoji pinched_fingers   @emoji :pinched_fingers: from "pinched_fingers"<br>
+  @emoji pinching_hand   @emoji :pinching_hand: from "pinching_hand"<br>
   @emoji pineapple   @emoji :pineapple: from "pineapple"<br>
   @emoji ping_pong   @emoji :ping_pong: from "ping_pong"<br>
+  @emoji pirate_flag   @emoji :pirate_flag: from "pirate_flag"<br>
   @emoji pisces   @emoji :pisces: from "pisces"<br>
   @emoji pitcairn_islands   @emoji :pitcairn_islands: from "pitcairn_islands"<br>
   @emoji pizza   @emoji :pizza: from "pizza"<br>
+  @emoji placard   @emoji :placard: from "placard"<br>
   @emoji place_of_worship   @emoji :place_of_worship: from "place_of_worship"<br>
   @emoji plate_with_cutlery   @emoji :plate_with_cutlery: from "plate_with_cutlery"<br>
   @emoji play_or_pause_button   @emoji :play_or_pause_button: from "play_or_pause_button"<br>
+  @emoji pleading_face   @emoji :pleading_face: from "pleading_face"<br>
+  @emoji plunger   @emoji :plunger: from "plunger"<br>
   @emoji point_down   @emoji :point_down: from "point_down"<br>
   @emoji point_left   @emoji :point_left: from "point_left"<br>
   @emoji point_right   @emoji :point_right: from "point_right"<br>
   @emoji point_up   @emoji :point_up: from "point_up"<br>
   @emoji point_up_2   @emoji :point_up_2: from "point_up_2"<br>
   @emoji poland   @emoji :poland: from "poland"<br>
+  @emoji polar_bear   @emoji :polar_bear: from "polar_bear"<br>
   @emoji police_car   @emoji :police_car: from "police_car"<br>
+  @emoji police_officer   @emoji :police_officer: from "police_officer"<br>
   @emoji policeman   @emoji :policeman: from "policeman"<br>
   @emoji policewoman   @emoji :policewoman: from "policewoman"<br>
   @emoji poodle   @emoji :poodle: from "poodle"<br>
   @emoji postbox   @emoji :postbox: from "postbox"<br>
   @emoji potable_water   @emoji :potable_water: from "potable_water"<br>
   @emoji potato   @emoji :potato: from "potato"<br>
+  @emoji potted_plant   @emoji :potted_plant: from "potted_plant"<br>
   @emoji pouch   @emoji :pouch: from "pouch"<br>
   @emoji poultry_leg   @emoji :poultry_leg: from "poultry_leg"<br>
   @emoji pound   @emoji :pound: from "pound"<br>
   @emoji pout   @emoji :pout: from "pout"<br>
   @emoji pouting_cat   @emoji :pouting_cat: from "pouting_cat"<br>
+  @emoji pouting_face   @emoji :pouting_face: from "pouting_face"<br>
   @emoji pouting_man   @emoji :pouting_man: from "pouting_man"<br>
   @emoji pouting_woman   @emoji :pouting_woman: from "pouting_woman"<br>
   @emoji pray   @emoji :pray: from "pray"<br>
   @emoji prayer_beads   @emoji :prayer_beads: from "prayer_beads"<br>
   @emoji pregnant_woman   @emoji :pregnant_woman: from "pregnant_woman"<br>
+  @emoji pretzel   @emoji :pretzel: from "pretzel"<br>
   @emoji previous_track_button   @emoji :previous_track_button: from "previous_track_button"<br>
   @emoji prince   @emoji :prince: from "prince"<br>
   @emoji princess   @emoji :princess: from "princess"<br>
   @emoji printer   @emoji :printer: from "printer"<br>
+  @emoji probing_cane   @emoji :probing_cane: from "probing_cane"<br>
   @emoji puerto_rico   @emoji :puerto_rico: from "puerto_rico"<br>
   @emoji punch   @emoji :punch: from "punch"<br>
+  @emoji purple_circle   @emoji :purple_circle: from "purple_circle"<br>
   @emoji purple_heart   @emoji :purple_heart: from "purple_heart"<br>
+  @emoji purple_square   @emoji :purple_square: from "purple_square"<br>
   @emoji purse   @emoji :purse: from "purse"<br>
   @emoji pushpin   @emoji :pushpin: from "pushpin"<br>
   @emoji put_litter_in_its_place   @emoji :put_litter_in_its_place: from "put_litter_in_its_place"<br>
   @emoji question   @emoji :question: from "question"<br>
   @emoji rabbit   @emoji :rabbit: from "rabbit"<br>
   @emoji rabbit2   @emoji :rabbit2: from "rabbit2"<br>
+  @emoji raccoon   @emoji :raccoon: from "raccoon"<br>
   @emoji racehorse   @emoji :racehorse: from "racehorse"<br>
   @emoji racing_car   @emoji :racing_car: from "racing_car"<br>
   @emoji radio   @emoji :radio: from "radio"<br>
   @emoji rainbow   @emoji :rainbow: from "rainbow"<br>
   @emoji rainbow_flag   @emoji :rainbow_flag: from "rainbow_flag"<br>
   @emoji raised_back_of_hand   @emoji :raised_back_of_hand: from "raised_back_of_hand"<br>
+  @emoji raised_eyebrow   @emoji :raised_eyebrow: from "raised_eyebrow"<br>
   @emoji raised_hand   @emoji :raised_hand: from "raised_hand"<br>
   @emoji raised_hand_with_fingers_splayed   @emoji :raised_hand_with_fingers_splayed: from "raised_hand_with_fingers_splayed"<br>
   @emoji raised_hands   @emoji :raised_hands: from "raised_hands"<br>
   @emoji ram   @emoji :ram: from "ram"<br>
   @emoji ramen   @emoji :ramen: from "ramen"<br>
   @emoji rat   @emoji :rat: from "rat"<br>
+  @emoji razor   @emoji :razor: from "razor"<br>
+  @emoji receipt   @emoji :receipt: from "receipt"<br>
   @emoji record_button   @emoji :record_button: from "record_button"<br>
   @emoji recycle   @emoji :recycle: from "recycle"<br>
   @emoji red_car   @emoji :red_car: from "red_car"<br>
   @emoji red_circle   @emoji :red_circle: from "red_circle"<br>
+  @emoji red_envelope   @emoji :red_envelope: from "red_envelope"<br>
+  @emoji red_haired_man   @emoji :red_haired_man: from "red_haired_man"<br>
+  @emoji red_haired_woman   @emoji :red_haired_woman: from "red_haired_woman"<br>
+  @emoji red_square   @emoji :red_square: from "red_square"<br>
   @emoji registered   @emoji :registered: from "registered"<br>
   @emoji relaxed   @emoji :relaxed: from "relaxed"<br>
   @emoji relieved   @emoji :relieved: from "relieved"<br>
   @emoji rice_scene   @emoji :rice_scene: from "rice_scene"<br>
   @emoji right_anger_bubble   @emoji :right_anger_bubble: from "right_anger_bubble"<br>
   @emoji ring   @emoji :ring: from "ring"<br>
+  @emoji ringed_planet   @emoji :ringed_planet: from "ringed_planet"<br>
   @emoji robot   @emoji :robot: from "robot"<br>
+  @emoji rock   @emoji :rock: from "rock"<br>
   @emoji rocket   @emoji :rocket: from "rocket"<br>
   @emoji rofl   @emoji :rofl: from "rofl"<br>
   @emoji roll_eyes   @emoji :roll_eyes: from "roll_eyes"<br>
+  @emoji roll_of_paper   @emoji :roll_of_paper: from "roll_of_paper"<br>
   @emoji roller_coaster   @emoji :roller_coaster: from "roller_coaster"<br>
+  @emoji roller_skate   @emoji :roller_skate: from "roller_skate"<br>
   @emoji romania   @emoji :romania: from "romania"<br>
   @emoji rooster   @emoji :rooster: from "rooster"<br>
   @emoji rose   @emoji :rose: from "rose"<br>
   @emoji running_woman   @emoji :running_woman: from "running_woman"<br>
   @emoji rwanda   @emoji :rwanda: from "rwanda"<br>
   @emoji sa   @emoji :sa: from "sa"<br>
+  @emoji safety_pin   @emoji :safety_pin: from "safety_pin"<br>
+  @emoji safety_vest   @emoji :safety_vest: from "safety_vest"<br>
   @emoji sagittarius   @emoji :sagittarius: from "sagittarius"<br>
   @emoji sailboat   @emoji :sailboat: from "sailboat"<br>
   @emoji sake   @emoji :sake: from "sake"<br>
+  @emoji salt   @emoji :salt: from "salt"<br>
   @emoji samoa   @emoji :samoa: from "samoa"<br>
   @emoji san_marino   @emoji :san_marino: from "san_marino"<br>
   @emoji sandal   @emoji :sandal: from "sandal"<br>
+  @emoji sandwich   @emoji :sandwich: from "sandwich"<br>
   @emoji santa   @emoji :santa: from "santa"<br>
   @emoji sao_tome_principe   @emoji :sao_tome_principe: from "sao_tome_principe"<br>
+  @emoji sari   @emoji :sari: from "sari"<br>
+  @emoji sassy_man   @emoji :sassy_man: from "sassy_man"<br>
+  @emoji sassy_woman   @emoji :sassy_woman: from "sassy_woman"<br>
   @emoji satellite   @emoji :satellite: from "satellite"<br>
   @emoji satisfied   @emoji :satisfied: from "satisfied"<br>
   @emoji saudi_arabia   @emoji :saudi_arabia: from "saudi_arabia"<br>
+  @emoji sauna_man   @emoji :sauna_man: from "sauna_man"<br>
+  @emoji sauna_person   @emoji :sauna_person: from "sauna_person"<br>
+  @emoji sauna_woman   @emoji :sauna_woman: from "sauna_woman"<br>
+  @emoji sauropod   @emoji :sauropod: from "sauropod"<br>
   @emoji saxophone   @emoji :saxophone: from "saxophone"<br>
+  @emoji scarf   @emoji :scarf: from "scarf"<br>
   @emoji school   @emoji :school: from "school"<br>
   @emoji school_satchel   @emoji :school_satchel: from "school_satchel"<br>
+  @emoji scientist   @emoji :scientist: from "scientist"<br>
   @emoji scissors   @emoji :scissors: from "scissors"<br>
   @emoji scorpion   @emoji :scorpion: from "scorpion"<br>
   @emoji scorpius   @emoji :scorpius: from "scorpius"<br>
+  @emoji scotland   @emoji :scotland: from "scotland"<br>
   @emoji scream   @emoji :scream: from "scream"<br>
   @emoji scream_cat   @emoji :scream_cat: from "scream_cat"<br>
+  @emoji screwdriver   @emoji :screwdriver: from "screwdriver"<br>
   @emoji scroll   @emoji :scroll: from "scroll"<br>
+  @emoji seal   @emoji :seal: from "seal"<br>
   @emoji seat   @emoji :seat: from "seat"<br>
   @emoji secret   @emoji :secret: from "secret"<br>
   @emoji see_no_evil   @emoji :see_no_evil: from "see_no_evil"<br>
   @emoji selfie   @emoji :selfie: from "selfie"<br>
   @emoji senegal   @emoji :senegal: from "senegal"<br>
   @emoji serbia   @emoji :serbia: from "serbia"<br>
+  @emoji service_dog   @emoji :service_dog: from "service_dog"<br>
   @emoji seven   @emoji :seven: from "seven"<br>
+  @emoji sewing_needle   @emoji :sewing_needle: from "sewing_needle"<br>
   @emoji seychelles   @emoji :seychelles: from "seychelles"<br>
   @emoji shallow_pan_of_food   @emoji :shallow_pan_of_food: from "shallow_pan_of_food"<br>
   @emoji shamrock   @emoji :shamrock: from "shamrock"<br>
   @emoji shoe   @emoji :shoe: from "shoe"<br>
   @emoji shopping   @emoji :shopping: from "shopping"<br>
   @emoji shopping_cart   @emoji :shopping_cart: from "shopping_cart"<br>
+  @emoji shorts   @emoji :shorts: from "shorts"<br>
   @emoji shower   @emoji :shower: from "shower"<br>
   @emoji shrimp   @emoji :shrimp: from "shrimp"<br>
+  @emoji shrug   @emoji :shrug: from "shrug"<br>
+  @emoji shushing_face   @emoji :shushing_face: from "shushing_face"<br>
   @emoji sierra_leone   @emoji :sierra_leone: from "sierra_leone"<br>
   @emoji signal_strength   @emoji :signal_strength: from "signal_strength"<br>
   @emoji singapore   @emoji :singapore: from "singapore"<br>
+  @emoji singer   @emoji :singer: from "singer"<br>
   @emoji sint_maarten   @emoji :sint_maarten: from "sint_maarten"<br>
   @emoji six   @emoji :six: from "six"<br>
   @emoji six_pointed_star   @emoji :six_pointed_star: from "six_pointed_star"<br>
+  @emoji skateboard   @emoji :skateboard: from "skateboard"<br>
   @emoji ski   @emoji :ski: from "ski"<br>
   @emoji skier   @emoji :skier: from "skier"<br>
   @emoji skull   @emoji :skull: from "skull"<br>
   @emoji skull_and_crossbones   @emoji :skull_and_crossbones: from "skull_and_crossbones"<br>
+  @emoji skunk   @emoji :skunk: from "skunk"<br>
+  @emoji sled   @emoji :sled: from "sled"<br>
   @emoji sleeping   @emoji :sleeping: from "sleeping"<br>
   @emoji sleeping_bed   @emoji :sleeping_bed: from "sleeping_bed"<br>
   @emoji sleepy   @emoji :sleepy: from "sleepy"<br>
   @emoji slightly_frowning_face   @emoji :slightly_frowning_face: from "slightly_frowning_face"<br>
   @emoji slightly_smiling_face   @emoji :slightly_smiling_face: from "slightly_smiling_face"<br>
   @emoji slot_machine   @emoji :slot_machine: from "slot_machine"<br>
+  @emoji sloth   @emoji :sloth: from "sloth"<br>
   @emoji slovakia   @emoji :slovakia: from "slovakia"<br>
   @emoji slovenia   @emoji :slovenia: from "slovenia"<br>
   @emoji small_airplane   @emoji :small_airplane: from "small_airplane"<br>
   @emoji smile_cat   @emoji :smile_cat: from "smile_cat"<br>
   @emoji smiley   @emoji :smiley: from "smiley"<br>
   @emoji smiley_cat   @emoji :smiley_cat: from "smiley_cat"<br>
+  @emoji smiling_face_with_tear   @emoji :smiling_face_with_tear: from "smiling_face_with_tear"<br>
+  @emoji smiling_face_with_three_hearts   @emoji :smiling_face_with_three_hearts: from "smiling_face_with_three_hearts"<br>
   @emoji smiling_imp   @emoji :smiling_imp: from "smiling_imp"<br>
   @emoji smirk   @emoji :smirk: from "smirk"<br>
   @emoji smirk_cat   @emoji :smirk_cat: from "smirk_cat"<br>
   @emoji snowflake   @emoji :snowflake: from "snowflake"<br>
   @emoji snowman   @emoji :snowman: from "snowman"<br>
   @emoji snowman_with_snow   @emoji :snowman_with_snow: from "snowman_with_snow"<br>
+  @emoji soap   @emoji :soap: from "soap"<br>
   @emoji sob   @emoji :sob: from "sob"<br>
   @emoji soccer   @emoji :soccer: from "soccer"<br>
+  @emoji socks   @emoji :socks: from "socks"<br>
+  @emoji softball   @emoji :softball: from "softball"<br>
   @emoji solomon_islands   @emoji :solomon_islands: from "solomon_islands"<br>
   @emoji somalia   @emoji :somalia: from "somalia"<br>
   @emoji soon   @emoji :soon: from "soon"<br>
   @emoji spider_web   @emoji :spider_web: from "spider_web"<br>
   @emoji spiral_calendar   @emoji :spiral_calendar: from "spiral_calendar"<br>
   @emoji spiral_notepad   @emoji :spiral_notepad: from "spiral_notepad"<br>
+  @emoji sponge   @emoji :sponge: from "sponge"<br>
   @emoji spoon   @emoji :spoon: from "spoon"<br>
   @emoji squid   @emoji :squid: from "squid"<br>
   @emoji sri_lanka   @emoji :sri_lanka: from "sri_lanka"<br>
   @emoji st_helena   @emoji :st_helena: from "st_helena"<br>
   @emoji st_kitts_nevis   @emoji :st_kitts_nevis: from "st_kitts_nevis"<br>
   @emoji st_lucia   @emoji :st_lucia: from "st_lucia"<br>
+  @emoji st_martin   @emoji :st_martin: from "st_martin"<br>
   @emoji st_pierre_miquelon   @emoji :st_pierre_miquelon: from "st_pierre_miquelon"<br>
   @emoji st_vincent_grenadines   @emoji :st_vincent_grenadines: from "st_vincent_grenadines"<br>
   @emoji stadium   @emoji :stadium: from "stadium"<br>
+  @emoji standing_man   @emoji :standing_man: from "standing_man"<br>
+  @emoji standing_person   @emoji :standing_person: from "standing_person"<br>
+  @emoji standing_woman   @emoji :standing_woman: from "standing_woman"<br>
   @emoji star   @emoji :star: from "star"<br>
   @emoji star2   @emoji :star2: from "star2"<br>
   @emoji star_and_crescent   @emoji :star_and_crescent: from "star_and_crescent"<br>
   @emoji star_of_david   @emoji :star_of_david: from "star_of_david"<br>
+  @emoji star_struck   @emoji :star_struck: from "star_struck"<br>
   @emoji stars   @emoji :stars: from "stars"<br>
   @emoji station   @emoji :station: from "station"<br>
   @emoji statue_of_liberty   @emoji :statue_of_liberty: from "statue_of_liberty"<br>
   @emoji steam_locomotive   @emoji :steam_locomotive: from "steam_locomotive"<br>
+  @emoji stethoscope   @emoji :stethoscope: from "stethoscope"<br>
   @emoji stew   @emoji :stew: from "stew"<br>
   @emoji stop_button   @emoji :stop_button: from "stop_button"<br>
   @emoji stop_sign   @emoji :stop_sign: from "stop_sign"<br>
   @emoji stuck_out_tongue   @emoji :stuck_out_tongue: from "stuck_out_tongue"<br>
   @emoji stuck_out_tongue_closed_eyes   @emoji :stuck_out_tongue_closed_eyes: from "stuck_out_tongue_closed_eyes"<br>
   @emoji stuck_out_tongue_winking_eye   @emoji :stuck_out_tongue_winking_eye: from "stuck_out_tongue_winking_eye"<br>
+  @emoji student   @emoji :student: from "student"<br>
   @emoji studio_microphone   @emoji :studio_microphone: from "studio_microphone"<br>
   @emoji stuffed_flatbread   @emoji :stuffed_flatbread: from "stuffed_flatbread"<br>
   @emoji sudan   @emoji :sudan: from "sudan"<br>
   @emoji sunny   @emoji :sunny: from "sunny"<br>
   @emoji sunrise   @emoji :sunrise: from "sunrise"<br>
   @emoji sunrise_over_mountains   @emoji :sunrise_over_mountains: from "sunrise_over_mountains"<br>
+  @emoji superhero   @emoji :superhero: from "superhero"<br>
+  @emoji superhero_man   @emoji :superhero_man: from "superhero_man"<br>
+  @emoji superhero_woman   @emoji :superhero_woman: from "superhero_woman"<br>
+  @emoji supervillain   @emoji :supervillain: from "supervillain"<br>
+  @emoji supervillain_man   @emoji :supervillain_man: from "supervillain_man"<br>
+  @emoji supervillain_woman   @emoji :supervillain_woman: from "supervillain_woman"<br>
   @emoji surfer   @emoji :surfer: from "surfer"<br>
   @emoji surfing_man   @emoji :surfing_man: from "surfing_man"<br>
   @emoji surfing_woman   @emoji :surfing_woman: from "surfing_woman"<br>
   @emoji suriname   @emoji :suriname: from "suriname"<br>
   @emoji sushi   @emoji :sushi: from "sushi"<br>
   @emoji suspension_railway   @emoji :suspension_railway: from "suspension_railway"<br>
+  @emoji svalbard_jan_mayen   @emoji :svalbard_jan_mayen: from "svalbard_jan_mayen"<br>
+  @emoji swan   @emoji :swan: from "swan"<br>
   @emoji swaziland   @emoji :swaziland: from "swaziland"<br>
   @emoji sweat   @emoji :sweat: from "sweat"<br>
   @emoji sweat_drops   @emoji :sweat_drops: from "sweat_drops"<br>
   @emoji sweat_smile   @emoji :sweat_smile: from "sweat_smile"<br>
   @emoji sweden   @emoji :sweden: from "sweden"<br>
   @emoji sweet_potato   @emoji :sweet_potato: from "sweet_potato"<br>
+  @emoji swim_brief   @emoji :swim_brief: from "swim_brief"<br>
   @emoji swimmer   @emoji :swimmer: from "swimmer"<br>
   @emoji swimming_man   @emoji :swimming_man: from "swimming_man"<br>
   @emoji swimming_woman   @emoji :swimming_woman: from "swimming_woman"<br>
   @emoji synagogue   @emoji :synagogue: from "synagogue"<br>
   @emoji syria   @emoji :syria: from "syria"<br>
   @emoji syringe   @emoji :syringe: from "syringe"<br>
+  @emoji t-rex   @emoji :t-rex: from "t-rex"<br>
   @emoji taco   @emoji :taco: from "taco"<br>
   @emoji tada   @emoji :tada: from "tada"<br>
   @emoji taiwan   @emoji :taiwan: from "taiwan"<br>
   @emoji tajikistan   @emoji :tajikistan: from "tajikistan"<br>
+  @emoji takeout_box   @emoji :takeout_box: from "takeout_box"<br>
+  @emoji tamale   @emoji :tamale: from "tamale"<br>
   @emoji tanabata_tree   @emoji :tanabata_tree: from "tanabata_tree"<br>
   @emoji tangerine   @emoji :tangerine: from "tangerine"<br>
   @emoji tanzania   @emoji :tanzania: from "tanzania"<br>
   @emoji taurus   @emoji :taurus: from "taurus"<br>
   @emoji taxi   @emoji :taxi: from "taxi"<br>
   @emoji tea   @emoji :tea: from "tea"<br>
+  @emoji teacher   @emoji :teacher: from "teacher"<br>
+  @emoji teapot   @emoji :teapot: from "teapot"<br>
+  @emoji technologist   @emoji :technologist: from "technologist"<br>
+  @emoji teddy_bear   @emoji :teddy_bear: from "teddy_bear"<br>
   @emoji telephone   @emoji :telephone: from "telephone"<br>
   @emoji telephone_receiver   @emoji :telephone_receiver: from "telephone_receiver"<br>
   @emoji telescope   @emoji :telescope: from "telescope"<br>
   @emoji tennis   @emoji :tennis: from "tennis"<br>
   @emoji tent   @emoji :tent: from "tent"<br>
+  @emoji test_tube   @emoji :test_tube: from "test_tube"<br>
   @emoji thailand   @emoji :thailand: from "thailand"<br>
   @emoji thermometer   @emoji :thermometer: from "thermometer"<br>
   @emoji thinking   @emoji :thinking: from "thinking"<br>
+  @emoji thong_sandal   @emoji :thong_sandal: from "thong_sandal"<br>
   @emoji thought_balloon   @emoji :thought_balloon: from "thought_balloon"<br>
+  @emoji thread   @emoji :thread: from "thread"<br>
   @emoji three   @emoji :three: from "three"<br>
   @emoji thumbsdown   @emoji :thumbsdown: from "thumbsdown"<br>
   @emoji thumbsup   @emoji :thumbsup: from "thumbsup"<br>
   @emoji timer_clock   @emoji :timer_clock: from "timer_clock"<br>
   @emoji timor_leste   @emoji :timor_leste: from "timor_leste"<br>
   @emoji tipping_hand_man   @emoji :tipping_hand_man: from "tipping_hand_man"<br>
+  @emoji tipping_hand_person   @emoji :tipping_hand_person: from "tipping_hand_person"<br>
   @emoji tipping_hand_woman   @emoji :tipping_hand_woman: from "tipping_hand_woman"<br>
   @emoji tired_face   @emoji :tired_face: from "tired_face"<br>
   @emoji tm   @emoji :tm: from "tm"<br>
   @emoji tomato   @emoji :tomato: from "tomato"<br>
   @emoji tonga   @emoji :tonga: from "tonga"<br>
   @emoji tongue   @emoji :tongue: from "tongue"<br>
+  @emoji toolbox   @emoji :toolbox: from "toolbox"<br>
+  @emoji tooth   @emoji :tooth: from "tooth"<br>
+  @emoji toothbrush   @emoji :toothbrush: from "toothbrush"<br>
   @emoji top   @emoji :top: from "top"<br>
   @emoji tophat   @emoji :tophat: from "tophat"<br>
   @emoji tornado   @emoji :tornado: from "tornado"<br>
   @emoji train   @emoji :train: from "train"<br>
   @emoji train2   @emoji :train2: from "train2"<br>
   @emoji tram   @emoji :tram: from "tram"<br>
+  @emoji transgender_flag   @emoji :transgender_flag: from "transgender_flag"<br>
+  @emoji transgender_symbol   @emoji :transgender_symbol: from "transgender_symbol"<br>
   @emoji triangular_flag_on_post   @emoji :triangular_flag_on_post: from "triangular_flag_on_post"<br>
   @emoji triangular_ruler   @emoji :triangular_ruler: from "triangular_ruler"<br>
   @emoji trident   @emoji :trident: from "trident"<br>
   @emoji trinidad_tobago   @emoji :trinidad_tobago: from "trinidad_tobago"<br>
+  @emoji tristan_da_cunha   @emoji :tristan_da_cunha: from "tristan_da_cunha"<br>
   @emoji triumph   @emoji :triumph: from "triumph"<br>
   @emoji trolleybus   @emoji :trolleybus: from "trolleybus"<br>
   @emoji trophy   @emoji :trophy: from "trophy"<br>
   @emoji underage   @emoji :underage: from "underage"<br>
   @emoji unicorn   @emoji :unicorn: from "unicorn"<br>
   @emoji united_arab_emirates   @emoji :united_arab_emirates: from "united_arab_emirates"<br>
+  @emoji united_nations   @emoji :united_nations: from "united_nations"<br>
   @emoji unlock   @emoji :unlock: from "unlock"<br>
   @emoji up   @emoji :up: from "up"<br>
   @emoji upside_down_face   @emoji :upside_down_face: from "upside_down_face"<br>
   @emoji uruguay   @emoji :uruguay: from "uruguay"<br>
   @emoji us   @emoji :us: from "us"<br>
+  @emoji us_outlying_islands   @emoji :us_outlying_islands: from "us_outlying_islands"<br>
   @emoji us_virgin_islands   @emoji :us_virgin_islands: from "us_virgin_islands"<br>
   @emoji uzbekistan   @emoji :uzbekistan: from "uzbekistan"<br>
   @emoji v   @emoji :v: from "v"<br>
+  @emoji vampire   @emoji :vampire: from "vampire"<br>
+  @emoji vampire_man   @emoji :vampire_man: from "vampire_man"<br>
+  @emoji vampire_woman   @emoji :vampire_woman: from "vampire_woman"<br>
   @emoji vanuatu   @emoji :vanuatu: from "vanuatu"<br>
   @emoji vatican_city   @emoji :vatican_city: from "vatican_city"<br>
   @emoji venezuela   @emoji :venezuela: from "venezuela"<br>
   @emoji virgo   @emoji :virgo: from "virgo"<br>
   @emoji volcano   @emoji :volcano: from "volcano"<br>
   @emoji volleyball   @emoji :volleyball: from "volleyball"<br>
+  @emoji vomiting_face   @emoji :vomiting_face: from "vomiting_face"<br>
   @emoji vs   @emoji :vs: from "vs"<br>
   @emoji vulcan_salute   @emoji :vulcan_salute: from "vulcan_salute"<br>
+  @emoji waffle   @emoji :waffle: from "waffle"<br>
+  @emoji wales   @emoji :wales: from "wales"<br>
   @emoji walking   @emoji :walking: from "walking"<br>
   @emoji walking_man   @emoji :walking_man: from "walking_man"<br>
   @emoji walking_woman   @emoji :walking_woman: from "walking_woman"<br>
   @emoji wastebasket   @emoji :wastebasket: from "wastebasket"<br>
   @emoji watch   @emoji :watch: from "watch"<br>
   @emoji water_buffalo   @emoji :water_buffalo: from "water_buffalo"<br>
+  @emoji water_polo   @emoji :water_polo: from "water_polo"<br>
   @emoji watermelon   @emoji :watermelon: from "watermelon"<br>
   @emoji wave   @emoji :wave: from "wave"<br>
   @emoji wavy_dash   @emoji :wavy_dash: from "wavy_dash"<br>
   @emoji wc   @emoji :wc: from "wc"<br>
   @emoji weary   @emoji :weary: from "weary"<br>
   @emoji wedding   @emoji :wedding: from "wedding"<br>
+  @emoji weight_lifting   @emoji :weight_lifting: from "weight_lifting"<br>
   @emoji weight_lifting_man   @emoji :weight_lifting_man: from "weight_lifting_man"<br>
   @emoji weight_lifting_woman   @emoji :weight_lifting_woman: from "weight_lifting_woman"<br>
   @emoji western_sahara   @emoji :western_sahara: from "western_sahara"<br>
   @emoji white_circle   @emoji :white_circle: from "white_circle"<br>
   @emoji white_flag   @emoji :white_flag: from "white_flag"<br>
   @emoji white_flower   @emoji :white_flower: from "white_flower"<br>
+  @emoji white_haired_man   @emoji :white_haired_man: from "white_haired_man"<br>
+  @emoji white_haired_woman   @emoji :white_haired_woman: from "white_haired_woman"<br>
+  @emoji white_heart   @emoji :white_heart: from "white_heart"<br>
   @emoji white_large_square   @emoji :white_large_square: from "white_large_square"<br>
   @emoji white_medium_small_square   @emoji :white_medium_small_square: from "white_medium_small_square"<br>
   @emoji white_medium_square   @emoji :white_medium_square: from "white_medium_square"<br>
   @emoji wilted_flower   @emoji :wilted_flower: from "wilted_flower"<br>
   @emoji wind_chime   @emoji :wind_chime: from "wind_chime"<br>
   @emoji wind_face   @emoji :wind_face: from "wind_face"<br>
+  @emoji window   @emoji :window: from "window"<br>
   @emoji wine_glass   @emoji :wine_glass: from "wine_glass"<br>
   @emoji wink   @emoji :wink: from "wink"<br>
   @emoji wolf   @emoji :wolf: from "wolf"<br>
   @emoji woman   @emoji :woman: from "woman"<br>
   @emoji woman_artist   @emoji :woman_artist: from "woman_artist"<br>
   @emoji woman_astronaut   @emoji :woman_astronaut: from "woman_astronaut"<br>
+  @emoji woman_beard   @emoji :woman_beard: from "woman_beard"<br>
   @emoji woman_cartwheeling   @emoji :woman_cartwheeling: from "woman_cartwheeling"<br>
   @emoji woman_cook   @emoji :woman_cook: from "woman_cook"<br>
+  @emoji woman_dancing   @emoji :woman_dancing: from "woman_dancing"<br>
   @emoji woman_facepalming   @emoji :woman_facepalming: from "woman_facepalming"<br>
   @emoji woman_factory_worker   @emoji :woman_factory_worker: from "woman_factory_worker"<br>
   @emoji woman_farmer   @emoji :woman_farmer: from "woman_farmer"<br>
+  @emoji woman_feeding_baby   @emoji :woman_feeding_baby: from "woman_feeding_baby"<br>
   @emoji woman_firefighter   @emoji :woman_firefighter: from "woman_firefighter"<br>
   @emoji woman_health_worker   @emoji :woman_health_worker: from "woman_health_worker"<br>
+  @emoji woman_in_manual_wheelchair   @emoji :woman_in_manual_wheelchair: from "woman_in_manual_wheelchair"<br>
+  @emoji woman_in_motorized_wheelchair   @emoji :woman_in_motorized_wheelchair: from "woman_in_motorized_wheelchair"<br>
+  @emoji woman_in_tuxedo   @emoji :woman_in_tuxedo: from "woman_in_tuxedo"<br>
   @emoji woman_judge   @emoji :woman_judge: from "woman_judge"<br>
   @emoji woman_juggling   @emoji :woman_juggling: from "woman_juggling"<br>
   @emoji woman_mechanic   @emoji :woman_mechanic: from "woman_mechanic"<br>
   @emoji woman_student   @emoji :woman_student: from "woman_student"<br>
   @emoji woman_teacher   @emoji :woman_teacher: from "woman_teacher"<br>
   @emoji woman_technologist   @emoji :woman_technologist: from "woman_technologist"<br>
+  @emoji woman_with_headscarf   @emoji :woman_with_headscarf: from "woman_with_headscarf"<br>
+  @emoji woman_with_probing_cane   @emoji :woman_with_probing_cane: from "woman_with_probing_cane"<br>
   @emoji woman_with_turban   @emoji :woman_with_turban: from "woman_with_turban"<br>
+  @emoji woman_with_veil   @emoji :woman_with_veil: from "woman_with_veil"<br>
   @emoji womans_clothes   @emoji :womans_clothes: from "womans_clothes"<br>
   @emoji womans_hat   @emoji :womans_hat: from "womans_hat"<br>
   @emoji women_wrestling   @emoji :women_wrestling: from "women_wrestling"<br>
   @emoji womens   @emoji :womens: from "womens"<br>
+  @emoji wood   @emoji :wood: from "wood"<br>
+  @emoji woozy_face   @emoji :woozy_face: from "woozy_face"<br>
   @emoji world_map   @emoji :world_map: from "world_map"<br>
+  @emoji worm   @emoji :worm: from "worm"<br>
   @emoji worried   @emoji :worried: from "worried"<br>
   @emoji wrench   @emoji :wrench: from "wrench"<br>
+  @emoji wrestling   @emoji :wrestling: from "wrestling"<br>
   @emoji writing_hand   @emoji :writing_hand: from "writing_hand"<br>
   @emoji x   @emoji :x: from "x"<br>
+  @emoji yarn   @emoji :yarn: from "yarn"<br>
+  @emoji yawning_face   @emoji :yawning_face: from "yawning_face"<br>
+  @emoji yellow_circle   @emoji :yellow_circle: from "yellow_circle"<br>
   @emoji yellow_heart   @emoji :yellow_heart: from "yellow_heart"<br>
+  @emoji yellow_square   @emoji :yellow_square: from "yellow_square"<br>
   @emoji yemen   @emoji :yemen: from "yemen"<br>
   @emoji yen   @emoji :yen: from "yen"<br>
   @emoji yin_yang   @emoji :yin_yang: from "yin_yang"<br>
+  @emoji yo_yo   @emoji :yo_yo: from "yo_yo"<br>
   @emoji yum   @emoji :yum: from "yum"<br>
   @emoji zambia   @emoji :zambia: from "zambia"<br>
+  @emoji zany_face   @emoji :zany_face: from "zany_face"<br>
   @emoji zap   @emoji :zap: from "zap"<br>
+  @emoji zebra   @emoji :zebra: from "zebra"<br>
   @emoji zero   @emoji :zero: from "zero"<br>
   @emoji zimbabwe   @emoji :zimbabwe: from "zimbabwe"<br>
   @emoji zipper_mouth_face   @emoji :zipper_mouth_face: from "zipper_mouth_face"<br>
+  @emoji zombie   @emoji :zombie: from "zombie"<br>
+  @emoji zombie_man   @emoji :zombie_man: from "zombie_man"<br>
+  @emoji zombie_woman   @emoji :zombie_woman: from "zombie_woman"<br>
   @emoji zzz   @emoji :zzz: from "zzz"<br>
+  @emoji blonde_man   @emoji :blonde_man: from "blonde_man"<br>
+  @emoji person_frowning   @emoji :person_frowning: from "person_frowning"<br>
+  @emoji person_with_blond_hair   @emoji :person_with_blond_hair: from "person_with_blond_hair"<br>
+  @emoji person_with_pouting_face   @emoji :person_with_pouting_face: from "person_with_pouting_face"<br>
   */
index 935ed11..a4c1ec9 100644 (file)
@@ -7,6 +7,7 @@
       <memberdef kind="enum" id="078__xml__namespace__members__in__file__scope_8h_1add172b93283b1ab7612c3ca6cc5dcfea" prot="public" static="no" strong="yes">
         <type/>
         <name>Enum</name>
+        <qualifiedname>Namespace::Enum</qualifiedname>
         <briefdescription>
           <para>An enum. </para>
         </briefdescription>
@@ -23,6 +24,7 @@
         <definition>void Namespace::foo</definition>
         <argsstring>()</argsstring>
         <name>foo</name>
+        <qualifiedname>Namespace::foo</qualifiedname>
         <briefdescription>
           <para>A function. </para>
         </briefdescription>
index fa5c853..13d2617 100644 (file)
@@ -8,6 +8,7 @@
         <definition>void Interface::load</definition>
         <argsstring>()</argsstring>
         <name>load</name>
+        <qualifiedname>Interface::load</qualifiedname>
         <briefdescription>
           <para>Load things. </para>
         </briefdescription>
@@ -25,6 +26,7 @@
         <definition>virtual void Interface::doLoad</definition>
         <argsstring>()=0</argsstring>
         <name>doLoad</name>
+        <qualifiedname>Interface::doLoad</qualifiedname>
         <briefdescription>
           <para>Pure virtual implementation for <ref refid="class_interface_1ab58d3008a7001cbb47f2fa5a5a1aeefa" kindref="member">load()</ref> </para>
         </briefdescription>
@@ -40,6 +42,7 @@
         <definition>virtual void Interface::doOtherStuff</definition>
         <argsstring>()</argsstring>
         <name>doOtherStuff</name>
+        <qualifiedname>Interface::doOtherStuff</qualifiedname>
         <briefdescription>
           <para>Non-pure virtual function. </para>
         </briefdescription>
@@ -55,6 +58,7 @@
         <definition>virtual void Interface::doSomethingUndocumented</definition>
         <argsstring>()</argsstring>
         <name>doSomethingUndocumented</name>
+        <qualifiedname>Interface::doSomethingUndocumented</qualifiedname>
         <briefdescription>
         </briefdescription>
         <detaileddescription>
@@ -68,6 +72,7 @@
         <definition>void Interface::someUtility</definition>
         <argsstring>()</argsstring>
         <name>someUtility</name>
+        <qualifiedname>Interface::someUtility</qualifiedname>
         <briefdescription>
           <para>A non-virtual private function, not extracted. </para>
         </briefdescription>
index 784e4e3..56b2c2b 100644 (file)
@@ -8,6 +8,7 @@
         <definition>int N::var</definition>
         <argsstring/>
         <name>var</name>
+        <qualifiedname>N::var</qualifiedname>
         <briefdescription>
           <para>variable declaration </para>
         </briefdescription>
@@ -25,6 +26,7 @@
         <definition>void N::foo</definition>
         <argsstring>(int param)</argsstring>
         <name>foo</name>
+        <qualifiedname>N::foo</qualifiedname>
         <param>
           <type>int</type>
           <declname>param</declname>
index d7fd8f9..cd6d7d9 100644 (file)
@@ -8,6 +8,7 @@
         <definition>int N::var</definition>
         <argsstring/>
         <name>var</name>
+        <qualifiedname>N::var</qualifiedname>
         <briefdescription>
           <para>variable declaration </para>
         </briefdescription>
@@ -25,6 +26,7 @@
         <definition>void N::foo</definition>
         <argsstring>(int param)</argsstring>
         <name>foo</name>
+        <qualifiedname>N::foo</qualifiedname>
         <param>
           <type>int</type>
           <declname>param</declname>
index 30e593d..291dec0 100644 (file)
@@ -12,10 +12,10 @@ of files (and tested against a DTD), it is also possible to create a pdf file
 for each test to see if the LaTeX / pdf generation is possible, similar for
 rtf and docbook output.
 
-The runtest.py script responsible for running the tests takes a number of
+The runtests.py script responsible for running the tests takes a number of
 optional parameters:
   --updateref           update the reference files. Should be used in
-                        combination with -id to update the reference file(s)
+                        combination with --id to update the reference file(s)
                         for the given test
   --doxygen [DOXYGEN]   path/name of the doxygen executable
   --xmllint [XMLLINT]   path/name of the xmllint executable
@@ -48,13 +48,13 @@ optional parameters:
 In case neither --xml, --xmlxsd, --pdf, --rtf, --docbook or --xhtml is used the
 default is set to --xml.
 
-The runtest.pl has the following dependencies on 3rd party tools:
+The runtests.py has the following dependencies on 3rd party tools:
 - python  to run the script
 - xmllint to normalize the XML output
 - diff    to show the differences in case a test fails
 
 Each test file can have a number of special comment lines that are extracted by
-the runtest.pl script and take the form:
+the runtests.py script and take the form:
 // <identifier>: 'argument'
 Where <identifier> can be one of:
 - objective: 'argument' provides the objective for the test (i.e. its purpose)
@@ -64,13 +64,13 @@ Where <identifier> can be one of:
              run doxygen on the test file.
 
 Example to run all tests:
-    python runtest.py
+    python runtests.py
 
 Example to run a test
-    python runtest.py -id 10
+    python runtests.py --id 10
 
 Example to update the reference files for a test
-    python runtest.py -updateref -id 10
+    python runtests.py --updateref --id 10
 
 There is also a CMakeLists.txt, which can be used from the build directory
 to run all tests by simply invoking 'make tests', to use the specific options use
index 30f000c..9b16182 100755 (executable)
@@ -595,7 +595,7 @@ def main():
        # argument handling
        parser = argparse.ArgumentParser(description='run doxygen tests')
        parser.add_argument('--updateref',help=
-               'update the reference files. Should be used in combination with -id to '
+               'update the reference files. Should be used in combination with --id to '
                'update the reference file(s) for the given test',action="store_true")
        parser.add_argument('--doxygen',nargs='?',default='doxygen',help=
                'path/name of the doxygen executable')
index 3b7b396..a0cd0e7 100644 (file)
@@ -3521,6 +3521,7 @@ void  VhdlParserTokenManager::SkipLexicalActions(Token *matchedToken){
          image.append(input_stream->GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
    {
      QCString q = filter2008VhdlComment(image.data());
+     parser->outlineParser()->lineCount(image.data());
      parser->outlineParser()->handleCommentBlock(QCString(q),TRUE);image.clear();
    }
          break;
index 388864a..559abc3 100644 (file)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
-# python script to generate configoptions.cpp and config.doc from config.xml
+# python script to adjust generated VhdlParser.cc
 #
-# Copyright (C) 1997-2020 by Dimitri van Heesch.
+# Copyright (C) 1997-2021 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
index 3ef732e..4f7a0b8 100755 (executable)
@@ -128,6 +128,7 @@ SKIP :
   {
    {
      QCString q = filter2008VhdlComment(image.data());
+     parser->outlineParser()->lineCount(image.data());
      parser->outlineParser()->handleCommentBlock(QCString(q),TRUE);image.clear();
    }
   }