summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--CMakeLists.txt5
-rw-r--r--README.md4
-rwxr-xr-xaddon/doxypysql/search.py124
-rwxr-xr-xaddon/doxywizard/doxywizard.cpp2
-rw-r--r--addon/doxywizard/expert.cpp5
-rw-r--r--addon/doxywizard/input.h1
-rw-r--r--addon/doxywizard/inputstring.h1
-rw-r--r--addon/doxywizard/inputstrlist.cpp8
-rw-r--r--addon/doxywizard/inputstrlist.h1
-rw-r--r--appveyor.yml23
-rw-r--r--cmake/FindSQLite3.cmake10
-rw-r--r--doc/CMakeLists.txt3
-rw-r--r--doc/Doxyfile2
-rw-r--r--doc/autolink.doc2
-rw-r--r--doc/changelog.doc2
-rw-r--r--doc/commands.doc98
-rw-r--r--doc/docblocks.doc19
-rw-r--r--doc/doxygen_manual.tex23
-rw-r--r--doc/emojisup.doc166
-rw-r--r--doc/features.doc4
-rw-r--r--doc/index.doc2
-rw-r--r--doc/install.doc6
-rw-r--r--doc/markdown.doc27
-rw-r--r--doc/output.doc2
-rw-r--r--doc/perlmod.doc2
-rw-r--r--doc/searching.doc4
-rw-r--r--doc/starting.doc2
-rw-r--r--doc/translator.py24
-rw-r--r--doc/xmlcmds.doc2
-rw-r--r--examples/jdstyle.cfg2
-rw-r--r--libmd5/md5.c2
-rw-r--r--qtools/qcstring.cpp32
-rw-r--r--qtools/qdatastream.cpp28
-rw-r--r--qtools/qgarray.cpp24
-rw-r--r--qtools/qgcache.cpp2
-rw-r--r--qtools/qgdict.cpp14
-rw-r--r--qtools/qglist.cpp24
-rw-r--r--qtools/qgvector.cpp4
-rw-r--r--qtools/qstring.cpp10
-rw-r--r--qtools/qtextstream.cpp4
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/cite.cpp4
-rw-r--r--src/classdef.cpp280
-rw-r--r--src/classdef.h4
-rw-r--r--src/cmdmapper.cpp1
-rw-r--r--src/cmdmapper.h3
-rw-r--r--src/code.l54
-rw-r--r--src/commentscan.h4
-rw-r--r--src/commentscan.l54
-rw-r--r--src/config.h2
-rw-r--r--src/config.xml1121
-rw-r--r--src/configimpl.h6
-rw-r--r--src/configimpl.l85
-rw-r--r--src/context.cpp168
-rw-r--r--src/defargs.l17
-rw-r--r--src/defgen.cpp36
-rw-r--r--src/definition.cpp257
-rw-r--r--src/diagram.cpp2
-rw-r--r--src/dirdef.cpp6
-rw-r--r--src/docbookgen.cpp2174
-rw-r--r--src/docbookgen.h18
-rw-r--r--src/docbookvisitor.cpp105
-rw-r--r--src/docbookvisitor.h21
-rw-r--r--src/docparser.cpp436
-rw-r--r--src/docparser.h28
-rw-r--r--src/docsets.cpp5
-rw-r--r--src/doctokenizer.h4
-rw-r--r--src/doctokenizer.l102
-rw-r--r--src/docvisitor.h2
-rw-r--r--src/dot.cpp17
-rw-r--r--src/dot.h14
-rw-r--r--src/doxygen.cpp252
-rw-r--r--src/doxygen.h1
-rw-r--r--src/emoji.cpp3187
-rw-r--r--src/emoji.h50
-rw-r--r--src/entry.cpp7
-rw-r--r--src/entry.h68
-rw-r--r--src/filedef.cpp151
-rw-r--r--src/filedef.h6
-rw-r--r--src/fortrancode.l17
-rw-r--r--src/fortranscanner.l50
-rw-r--r--src/ftvhelp.cpp46
-rw-r--r--src/groupdef.cpp6
-rw-r--r--src/htmldocvisitor.cpp142
-rw-r--r--src/htmldocvisitor.h1
-rw-r--r--src/htmlentity.cpp3
-rw-r--r--src/htmlgen.cpp69
-rw-r--r--src/index.cpp913
-rw-r--r--src/index.h24
-rw-r--r--src/latexdocvisitor.cpp125
-rw-r--r--src/latexdocvisitor.h1
-rw-r--r--src/latexgen.cpp55
-rw-r--r--src/layout.cpp198
-rw-r--r--src/layout.h17
-rw-r--r--src/layout_default.xml32
-rw-r--r--src/mandocvisitor.cpp17
-rw-r--r--src/mandocvisitor.h1
-rw-r--r--src/markdown.cpp58
-rw-r--r--src/marshal.cpp6
-rw-r--r--src/memberdef.cpp120
-rw-r--r--src/memberdef.h11
-rw-r--r--src/membergroup.cpp10
-rw-r--r--src/membergroup.h2
-rw-r--r--src/memberlist.cpp64
-rw-r--r--src/memberlist.h26
-rw-r--r--src/namespacedef.cpp189
-rw-r--r--src/namespacedef.h18
-rw-r--r--src/perlmodgen.cpp40
-rw-r--r--src/portable.cpp4
-rw-r--r--src/pre.l2
-rw-r--r--src/printdocvisitor.h20
-rw-r--r--src/pyscanner.l166
-rw-r--r--src/reflist.cpp39
-rw-r--r--src/rtfdocvisitor.cpp106
-rw-r--r--src/rtfdocvisitor.h11
-rw-r--r--src/rtfgen.cpp3
-rw-r--r--src/scanner.l235
-rw-r--r--src/searchindex.cpp119
-rw-r--r--src/searchindex.h37
-rw-r--r--src/sqlite3gen.cpp2160
-rw-r--r--src/tagreader.cpp64
-rw-r--r--src/template.cpp4
-rw-r--r--src/textdocvisitor.cpp13
-rw-r--r--src/textdocvisitor.h1
-rw-r--r--src/translator.h32
-rw-r--r--src/translator_adapter.h89
-rw-r--r--src/translator_br.h11
-rw-r--r--src/translator_de.h8
-rw-r--r--src/translator_en.h136
-rw-r--r--src/translator_es.h248
-rw-r--r--src/translator_fr.h252
-rw-r--r--src/translator_nl.h77
-rw-r--r--src/translator_pt.h6
-rw-r--r--src/types.h22
-rw-r--r--src/util.cpp94
-rw-r--r--src/util.h30
-rw-r--r--src/vhdlcode.l69
-rw-r--r--src/vhdldocgen.cpp11
-rw-r--r--src/xmldocvisitor.cpp24
-rw-r--r--src/xmldocvisitor.h1
-rw-r--r--src/xmlgen.cpp267
-rw-r--r--src/xmlgen.h42
-rw-r--r--templates/html/doxygen.css2
-rw-r--r--templates/html/header.html2
-rw-r--r--templates/html/htmlbase.tpl2
-rw-r--r--templates/html/htmlsearchresult.tpl2
-rw-r--r--templates/latex/doxygen.sty6
-rw-r--r--testing/009/bug.xml9
-rw-r--r--testing/009/deprecated.xml8
-rw-r--r--testing/009/reminders.xml8
-rw-r--r--testing/009/test.xml8
-rw-r--r--testing/009/todo.xml8
-rw-r--r--testing/012/citelist.xml2
-rw-r--r--testing/README.txt12
-rw-r--r--testing/runtests.py115
156 files changed, 11553 insertions, 4770 deletions
diff --git a/.travis.yml b/.travis.yml
index 7a370da..829e54e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -29,6 +29,8 @@ jobs:
before_script:
- if [ "${TRAVIS_OS_NAME}" == "osx" ]; then
+ sudo mkdir -p /usr/local/man;
+ sudo chown -R "${USER}:admin" /usr/local/man;
pip install --quiet conan;
export HOMEBREW_NO_AUTO_UPDATE=1;
brew install ghostscript;
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1e0fb55..45c2f2c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -86,7 +86,10 @@ find_package(BISON REQUIRED)
find_package(Threads)
if (sqlite3)
- find_package(SQLite3 REQUIRED)
+ find_package(SQLite3 REQUIRED)
+ if (SQLITE3_VERSION VERSION_LESS 3.9.0)
+ message(SEND_ERROR "Doxygen requires at least sqlite3 version 3.9.0 (installed: ${SQLITE3_VERSION})")
+ endif()
endif()
find_package(Iconv REQUIRED)
diff --git a/README.md b/README.md
index ab3f7fc..3e1c608 100644
--- a/README.md
+++ b/README.md
@@ -36,9 +36,7 @@ Developers
* Doxygen's Doxygen Documentation: <a href="https://codedocs.xyz/doxygen/doxygen/"><img src="https://codedocs.xyz/doxygen/doxygen.svg"/></a>
-* Install
- * Quick install see (./INSTALL)
- * else http://www.doxygen.org/manual/install.html
+* Install: Please read the installation section of the manual (http://www.doxygen.org/manual/install.html)
* Project stats: https://www.openhub.net/p/doxygen
diff --git a/addon/doxypysql/search.py b/addon/doxypysql/search.py
index c185138..5f820de 100755
--- a/addon/doxypysql/search.py
+++ b/addon/doxypysql/search.py
@@ -17,19 +17,19 @@ import json
import re
class MemberType:
- Define="0"
- Function="1"
- Variable="2"
- Typedef="3"
- Enumeration="4"
- EnumValue="5"
- Signal="6"
- Slot="7"
- Friend="8"
- DCOP="9"
- Property="10"
- Event="11"
- File="12"
+ Define="macro definition"
+ Function="function"
+ Variable="variable"
+ Typedef="typedef"
+ Enumeration="enumeration"
+ EnumValue="enumvalue"
+ Signal="signal"
+ Slot="slot"
+ Friend="friend"
+ DCOP="dcop"
+ Property="property"
+ Event="event"
+ File="file"
class RequestType:
References="9901"
@@ -69,27 +69,27 @@ class Finder:
def match(self,row):
if self.row_type is int:
- return " id=?"
+ return " rowid=?"
else:
if g_use_regexp == True:
return " REGEXP (?,%s)" %row
else:
return " %s=?" %row
- def fileName(self,id_file):
- if self.cn.execute("SELECT COUNT(*) FROM files WHERE rowid=?",[id_file]).fetchone()[0] > 1:
- print >>sys.stderr,"WARNING: non-uniq fileid [%s]. Considering only the first match." % id_file
+ def fileName(self,file_id):
+ if self.cn.execute("SELECT COUNT(*) FROM path WHERE rowid=?",[file_id]).fetchone()[0] > 1:
+ sys.stderr.write("WARNING: non-uniq fileid [%s]. Considering only the first match." % file_id)
- for r in self.cn.execute("SELECT * FROM files WHERE rowid=?",[id_file]).fetchall():
+ for r in self.cn.execute("SELECT * FROM path WHERE rowid=?",[file_id]).fetchall():
return r['name']
return ""
def fileId(self,name):
- if self.cn.execute("SELECT COUNT(*) FROM files WHERE"+self.match("name"),[name]).fetchone()[0] > 1:
- print >>sys.stderr,"WARNING: non-uniq file name [%s]. Considering only the first match." % name
+ if self.cn.execute("SELECT COUNT(*) FROM path WHERE"+self.match("name"),[name]).fetchone()[0] > 1:
+ sys.stderr.write("WARNING: non-uniq file name [%s]. Considering only the first match." % name)
- for r in self.cn.execute("SELECT rowid FROM files WHERE"+self.match("name"),[name]).fetchall():
+ for r in self.cn.execute("SELECT rowid FROM path WHERE"+self.match("name"),[name]).fetchall():
return r[0]
return -1
@@ -97,23 +97,24 @@ class Finder:
def references(self):
o=[]
cur = self.cn.cursor()
- cur.execute("SELECT refid FROM memberdef WHERE"+self.match("name"),[self.name])
- refids = cur.fetchall()
+ cur.execute("SELECT rowid FROM memberdef WHERE"+self.match("name"),[self.name])
+ rowids = cur.fetchall()
- if len(refids) == 0:
+ if len(rowids) == 0:
return o
- refid = refids[0]['refid']
+ rowid = rowids[0]['rowid']
cur = self.cn.cursor()
- #TODO:SELECT rowid from refids where refid=refid
- for info in cur.execute("SELECT * FROM xrefs WHERE refid_dst LIKE '%"+refid+"%'"):
+ #TODO:SELECT rowid from refid where refid=refid
+ for info in cur.execute("SELECT * FROM xrefs WHERE dst_rowid=?", [rowid]):
item={}
cur = self.cn.cursor()
- for i2 in cur.execute("SELECT * FROM memberdef WHERE refid=?",[info['src']]):
+ for i2 in cur.execute("SELECT * FROM memberdef WHERE rowid=?",[info['src_rowid']]):
item['name']=i2['name']
- item['src']=info['src']
- item['file']=self.fileName(info['id_file'])
- item['line']=info['line']
+ item['src']=info['src_rowid']
+ # Below no longer directly supported on this entry; can be found from either memberdef
+ #item['file']=self.fileName(info['file_id'])
+ #item['line']=info['line']
o.append(item)
return o
@@ -126,7 +127,7 @@ class Finder:
item['name'] = r['name']
item['definition'] = r['definition']
item['argsstring'] = r['argsstring']
- item['file'] = self.fileName(r['id_file'])
+ item['file'] = self.fileName(r['file_id'])
item['line'] = r['line']
item['detaileddescription'] = r['detaileddescription']
o.append(item)
@@ -134,7 +135,7 @@ class Finder:
###############################################################################
def file(self):
o=[]
- for r in self.cn.execute("SELECT rowid,* FROM files WHERE"+self.match("name"),[self.name]).fetchall():
+ for r in self.cn.execute("SELECT rowid,name FROM local_file WHERE"+self.match("name"),[self.name]).fetchall():
item={}
item['name'] = r['name']
item['id'] = r['rowid']
@@ -151,7 +152,7 @@ class Finder:
if r['argsstring']:
item['argsstring'] = r['argsstring']
item['definition'] = r['initializer']
- item['file'] = self.fileName(r['id_file'])
+ item['file'] = self.fileName(r['file_id'])
item['line'] = r['line']
o.append(item)
return o
@@ -163,7 +164,7 @@ class Finder:
item={}
item['name'] = r['name']
item['definition'] = r['definition']
- item['file'] = self.fileName(r['id_file'])
+ item['file'] = self.fileName(r['file_id'])
item['line'] = r['line']
o.append(item)
return o
@@ -175,16 +176,16 @@ class Finder:
item={}
item['name'] = r['name']
item['definition'] = r['definition']
- item['file'] = self.fileName(r['id_file'])
+ item['file'] = self.fileName(r['file_id'])
item['line'] = r['line']
o.append(item)
return o
###############################################################################
def params(self):
o=[]
- c=self.cn.execute('SELECT id FROM memberdef WHERE'+self.match("name"),[self.name])
+ c=self.cn.execute('SELECT rowid FROM memberdef WHERE'+self.match("name"),[self.name])
for r in c.fetchall():
- #a=("SELECT * FROM params where id=(SELECT id_param FROM memberdef_params where id_memberdef=?",[id_memberdef])
+ #a=("SELECT * FROM param where id=(SELECT param_id FROM memberdef_param where memberdef_id=?",[memberdef_id])
item={}
item['id'] = r['id']
o.append(item)
@@ -202,20 +203,20 @@ class Finder:
def includers(self):
o=[]
fid = self.fileId(self.name)
- c=self.cn.execute('SELECT * FROM includes WHERE id_dst=?',[fid])
+ c=self.cn.execute('SELECT * FROM includes WHERE dst_id=?',[fid])
for r in c.fetchall():
item={}
- item['name'] = self.fileName(r['id_src'])
+ item['name'] = self.fileName(r['src_id'])
o.append(item)
return o
###############################################################################
def includees(self):
o=[]
fid = self.fileId(self.name)
- c=self.cn.execute('SELECT * FROM includes WHERE id_src=?',[fid])
+ c=self.cn.execute('SELECT * FROM includes WHERE src_id=?',[fid])
for r in c.fetchall():
item={}
- item['name'] = self.fileName(r['id_dst'])
+ item['name'] = self.fileName(r['dst_id'])
o.append(item)
return o
###############################################################################
@@ -227,7 +228,7 @@ class Finder:
item['name'] = r['name']
item['definition'] = r['definition']
item['argsstring'] = r['argsstring']
- item['file'] = self.fileName(r['id_file'])
+ item['file'] = self.fileName(r['file_id'])
item['line'] = r['line']
#item['documentation'] = r['documentation']
o.append(item)
@@ -235,19 +236,19 @@ class Finder:
###############################################################################
def baseClasses(self):
o=[]
- c=self.cn.execute('SELECT base FROM basecompoundref WHERE'+self.match("derived"),[self.name])
+ c=self.cn.execute('SELECT compounddef.name FROM compounddef JOIN compoundref ON compounddef.rowid=compoundref.base_rowid WHERE compoundref.derived_rowid IN (SELECT rowid FROM compounddef WHERE'+self.match("name")+')',[self.name])
for r in c.fetchall():
item={}
- item['name'] = r['base']
+ item['name'] = r['name']
o.append(item)
return o
###############################################################################
def subClasses(self):
o=[]
- c=self.cn.execute('SELECT derived FROM basecompoundref WHERE'+self.match("base"),[self.name])
+ c=self.cn.execute('SELECT compounddef.name FROM compounddef JOIN compoundref ON compounddef.rowid=compoundref.derived_rowid WHERE compoundref.base_rowid IN (SELECT rowid FROM compounddef WHERE'+self.match("name")+')',[self.name])
for r in c.fetchall():
item={}
- item['name'] = r['derived']
+ item['name'] = r['name']
o.append(item)
return o
###############################################################################
@@ -268,21 +269,23 @@ def process(f,kind):
}
return request_processors[kind]()
###############################################################################
+
+# the -H option isn't documented. It's one of the more recent additions, but it's treating refids as if they would be a string. I'm just taking a stab at updating it for now, converting to use rowid, and making other edits necessary to get it to run.
def processHref(cn,ref):
j={}
# is it in memberdef ?
table="memberdef"
- if ( cn.execute("SELECT count(*) from %s WHERE refid=?"%table,[ref] ).fetchone()[0] > 0 ):
- for r in cn.execute("SELECT kind,id FROM %s WHERE refid='%s'" % (table,ref) ).fetchall():
- f=Finder(cn,r['id'],int)
+ if ( cn.execute("SELECT count(*) from %s WHERE rowid=?"%table,[ref] ).fetchone()[0] > 0 ):
+ for r in cn.execute("SELECT kind,rowid FROM %s WHERE rowid=?" % table,[ref]).fetchall():
+ f=Finder(cn,r['rowid'],int)
j=process(f,str(r['kind']))
# is it in compounddef ?
table="compounddef"
- if ( cn.execute("SELECT count(*) from %s WHERE refid=?"%table,[ref]).fetchone()[0] > 0 ):
- for r in cn.execute("SELECT id FROM %s WHERE refid=?"%table,[ref] ).fetchall():
- f=Finder(cn,r['id'],int)
+ if ( cn.execute("SELECT count(*) from %s WHERE rowid=?"%table,[ref]).fetchone()[0] > 0 ):
+ for r in cn.execute("SELECT rowid FROM %s WHERE rowid=?"%table,[ref] ).fetchall():
+ f=Finder(cn,r[0],int)
j=process(f,RequestType.Struct)
return j
@@ -290,7 +293,7 @@ def processHref(cn,ref):
def serveCgi():
import cgi
- print 'Content-Type: application/json\n'
+ print('Content-Type: application/json\n')
fieldStorage = cgi.FieldStorage()
form = dict((key, fieldStorage.getvalue(key)) for key in fieldStorage.keys())
@@ -298,17 +301,17 @@ def serveCgi():
if 'href' in form:
ref = form['href']
else:
- print '{"result": null, "error": "no refid given"}'
+ print('{"result": null, "error": "no refid given"}')
sys.exit(0)
cn=openDb('doxygen_sqlite3.db')
j = processHref(cn,ref)
- print json.dumps({"result":j,"error":None})
+ print(json.dumps({"result":j,"error":None}))
###############################################################################
def usage():
- print >>sys.stderr,"""Usage: search.py [Options]
+ sys.stderr.write("""Usage: search.py [Options]
Options:
-h, --help
-d <D> Use database <D> for queries.
@@ -323,7 +326,7 @@ Options:
-M <C> Get all members of class <C>.
-S <C> Get the sub classes of class <C>.
-R Consider the search <term> to be a regex.
-"""
+""")
###############################################################################
def serveCli(argv):
try:
@@ -362,6 +365,8 @@ def serveCli(argv):
elif a in ('-f'):
kind=MemberType.Function
elif a in ('-F'):
+ # undocumented
+ # seems to fit with the lower case "search" patterns?
kind=MemberType.File
elif a in ('-m'):
kind=MemberType.Define
@@ -370,6 +375,7 @@ def serveCli(argv):
elif a in ('-v'):
kind=MemberType.Variable
elif a in ('-H'):
+ # undocumented
ref = o
cn=openDb(dbname)
@@ -378,7 +384,7 @@ def serveCli(argv):
j=processHref(cn,ref)
else:
j=process(f,kind)
- print json.dumps(j,indent=4)
+ print(json.dumps(j,indent=4))
def main(argv):
diff --git a/addon/doxywizard/doxywizard.cpp b/addon/doxywizard/doxywizard.cpp
index 492912b..4e0d1aa 100755
--- a/addon/doxywizard/doxywizard.cpp
+++ b/addon/doxywizard/doxywizard.cpp
@@ -267,7 +267,7 @@ void MainWindow::saveConfig(const QString &fileName)
{
if (fileName.isEmpty()) return;
QFile f(fileName);
- if (!f.open(QIODevice::WriteOnly))
+ if (!f.open(QIODevice::WriteOnly | QIODevice::Text ))
{
QMessageBox::warning(this,
tr("Error saving"),
diff --git a/addon/doxywizard/expert.cpp b/addon/doxywizard/expert.cpp
index 66a0955..44dea78 100644
--- a/addon/doxywizard/expert.cpp
+++ b/addon/doxywizard/expert.cpp
@@ -765,9 +765,10 @@ void Expert::saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec,
t << convertToComment(option->templateDocs());
t << endl;
}
- t << name.leftJustified(MAX_OPTION_LENGTH) << "= ";
- if (option)
+ t << name.leftJustified(MAX_OPTION_LENGTH) << "=";
+ if (option && !option->isEmpty())
{
+ t << " ";
option->writeValue(t,codec);
}
t << endl;
diff --git a/addon/doxywizard/input.h b/addon/doxywizard/input.h
index 9e0a1bf..5d86cc8 100644
--- a/addon/doxywizard/input.h
+++ b/addon/doxywizard/input.h
@@ -30,6 +30,7 @@ class Input
virtual void reset() = 0;
virtual void writeValue(QTextStream &t,QTextCodec *codec) = 0;
virtual void setTemplateDocs(const QString &docs) = 0;
+ virtual bool isEmpty() { return false; };
};
diff --git a/addon/doxywizard/inputstring.h b/addon/doxywizard/inputstring.h
index dba31f6..6234256 100644
--- a/addon/doxywizard/inputstring.h
+++ b/addon/doxywizard/inputstring.h
@@ -60,6 +60,7 @@ class InputString : public QObject, public Input
void updateDependencies() {}
void writeValue(QTextStream &t,QTextCodec *codec);
void setTemplateDocs(const QString &docs) { m_tdocs = docs; }
+ bool isEmpty() { return m_str.isEmpty(); }
public slots:
void reset();
diff --git a/addon/doxywizard/inputstrlist.cpp b/addon/doxywizard/inputstrlist.cpp
index 660ce40..822bc4c 100644
--- a/addon/doxywizard/inputstrlist.cpp
+++ b/addon/doxywizard/inputstrlist.cpp
@@ -260,3 +260,11 @@ void InputStrList::writeValue(QTextStream &t,QTextCodec *codec)
}
}
+bool InputStrList::isEmpty()
+{
+ foreach (QString s, m_strList)
+ {
+ if (!s.isEmpty()) return false;
+ }
+ return true;
+}
diff --git a/addon/doxywizard/inputstrlist.h b/addon/doxywizard/inputstrlist.h
index 53f3bcc..c374092 100644
--- a/addon/doxywizard/inputstrlist.h
+++ b/addon/doxywizard/inputstrlist.h
@@ -55,6 +55,7 @@ class InputStrList : public QObject, public Input
void updateDependencies() {}
void writeValue(QTextStream &t,QTextCodec *codec);
void setTemplateDocs(const QString &docs) { m_tdocs = docs; }
+ bool isEmpty();
public slots:
void reset();
diff --git a/appveyor.yml b/appveyor.yml
index 1119f38..bbafb40 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -22,18 +22,21 @@ init:
install:
- ps: Invoke-WebRequest https://github.com/lexxmark/winflexbison/releases/download/v2.5.15/win_flex_bison-2.5.15.zip -OutFile flex.zip
- 7z x flex.zip -oC:\deps\flex
- - ps: Invoke-WebRequest https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs924/gs924w32.exe -OutFile gswin32c.exe
- - gswin32c /S /D=C:\deps\ghostscript
- - ps: if($env:platform -eq "x64") { Invoke-WebRequest https://miktex.org/download/win/miktexsetup-x64.zip -OutFile miktexsetup.zip }
- - ps: if($env:platform -eq "Win32") { Invoke-WebRequest https://miktex.org/download/win/miktexsetup-x86.zip -OutFile miktexsetup.zip }
- - 7z x miktexsetup.zip -oC:\tmpmiktex
- - C:\tmpmiktex\miktexsetup --local-package-repository=C:\temp\miktex --package-set=basic download
- - C:\tmpmiktex\miktexsetup --verbose --local-package-repository=C:\temp\miktex --package-set=basic install
+ - ps: Invoke-WebRequest http://doxygen.nl/testing/miktex.zip -OutFile miktex.zip
+ - 7z x miktex.zip -oC:\deps\miktex
+# Disabled MikTeX installed due to unreliable download
+# - ps: Invoke-WebRequest https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs924/gs924w32.exe -OutFile gswin32c.exe
+# - gswin32c /S /D=C:\deps\ghostscript
+# - ps: if($env:platform -eq "x64") { Invoke-WebRequest https://miktex.org/download/win/miktexsetup-x64.zip -OutFile miktexsetup.zip }
+# - ps: if($env:platform -eq "Win32") { Invoke-WebRequest https://miktex.org/download/win/miktexsetup-x86.zip -OutFile miktexsetup.zip }
+# - 7z x miktexsetup.zip -oC:\tmpmiktex
+# - C:\tmpmiktex\miktexsetup --local-package-repository=C:\temp\miktex --package-set=basic download
+# - C:\tmpmiktex\miktexsetup --verbose --local-package-repository=C:\temp\miktex --package-set=basic install
- refreshenv
- pip install conan
- conan install libxml2/2.9.8@bincrafters/stable -g virtualrunenv
- activate_run.bat
- - set "PATH=%PATH%;C:\deps\ghostscript\bin;C:\deps\flex"
+ - set "PATH=%PATH%;C:\deps\ghostscript\bin;C:\deps\flex;C:\deps\miktex\miktex\bin"
before_build:
- if "%platform%"=="Win32" ( set "CMAKE_GENERATOR_NAME=Visual Studio %VSVERSION%" )
@@ -48,5 +51,7 @@ build:
test_script:
- msbuild "testing\tests.vcxproj" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
- - cmake -G "%CMAKE_GENERATOR_NAME%" -D build_doc=ON ..
+# Disabled building document due to unreliable MikTeX installation
+# - cmake -G "%CMAKE_GENERATOR_NAME%" -D build_doc=ON ..
+ - cmake -G "%CMAKE_GENERATOR_NAME%" ..
# - msbuild "doc\docs.vcxproj" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
diff --git a/cmake/FindSQLite3.cmake b/cmake/FindSQLite3.cmake
index 77b8eb4..45cc212 100644
--- a/cmake/FindSQLite3.cmake
+++ b/cmake/FindSQLite3.cmake
@@ -71,8 +71,16 @@ else (SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS)
endif (SQLITE3_INCLUDE_DIRS AND SQLITE3_LIBRARIES)
if (SQLITE3_FOUND)
+
+ # Extract version from header file
+ find_file(SQLITE3_HEADER "sqlite3.h" HINTS ${SQLITE3_INCLUDE_DIRS})
+ if(SQLITE3_HEADER)
+ file(STRINGS "${SQLITE3_HEADER}" _DEF_TMP REGEX "^#define SQLITE_VERSION +\\\"[^\\\"]+\\\"")
+ string (REGEX REPLACE ".*\\\"(([0-9]+[.]?)+).*" "\\1" SQLITE3_VERSION "${_DEF_TMP}")
+ endif (SQLITE3_HEADER)
+
if (NOT Sqlite3_FIND_QUIETLY)
- message(STATUS "Found Sqlite3: ${SQLITE3_LIBRARIES}")
+ message(STATUS "Found Sqlite3: ${SQLITE3_LIBRARIES} (found version \"${SQLITE3_VERSION}\")")
endif (NOT Sqlite3_FIND_QUIETLY)
else (SQLITE3_FOUND)
if (Sqlite3_FIND_REQUIRED)
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index b95afd8..e940622 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -80,6 +80,7 @@ set(DOC_FILES
starting.doc
trouble.doc
xmlcmds.doc
+ emojisup.doc
language.tpl
maintainers.txt
translator.py
@@ -113,7 +114,7 @@ configure_file(${CMAKE_SOURCE_DIR}/doc/doxyindexer.1 ${PROJECT_BINARY_DIR}/
# doc/language.doc (see tag Doxyfile:INPUT)
add_custom_command(
- COMMAND ${PYTHON_EXECUTABLE} translator.py
+ COMMAND ${PYTHON_EXECUTABLE} translator.py ${CMAKE_SOURCE_DIR}
DEPENDS ${PROJECT_BINARY_DIR}/doc/maintainers.txt ${PROJECT_BINARY_DIR}/doc/language.tpl ${PROJECT_BINARY_DIR}/doc/translator.py
OUTPUT language.doc
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc
diff --git a/doc/Doxyfile b/doc/Doxyfile
index ceb6385..bdd1098 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -38,7 +38,7 @@ INPUT = index.doc install.doc starting.doc docblocks.doc markdown.do
autolink.doc output.doc searching.doc extsearch.doc customize.doc custcmd.doc \
external.doc faq.doc trouble.doc features.doc \
doxygen_usage.doc doxywizard_usage.doc \
- config.doc commands.doc htmlcmds.doc xmlcmds.doc language.doc \
+ config.doc commands.doc htmlcmds.doc xmlcmds.doc emojisup.doc language.doc \
perlmod.doc perlmod_tree.doc arch.doc changelog.doc
FILE_PATTERNS = *.cpp *.h *.doc
EXAMPLE_PATH = ../examples
diff --git a/doc/autolink.doc b/doc/autolink.doc
index ff468e4..bf9fe57 100644
--- a/doc/autolink.doc
+++ b/doc/autolink.doc
@@ -80,7 +80,7 @@
are required to identify the target, i.e. 'func(int) const' and 'func(int)'
target different member functions.
\par Note 3:
- For JavaDoc compatibility a \# may be used instead of a :: in
+ For Javadoc compatibility a \# may be used instead of a :: in
the patterns above.
\par Note 4:
In the documentation of a class containing a member foo,
diff --git a/doc/changelog.doc b/doc/changelog.doc
index 3ba6787..ca00728 100644
--- a/doc/changelog.doc
+++ b/doc/changelog.doc
@@ -2182,7 +2182,7 @@ make sure you add the following:
<h3>New features</h3>
<ul>
<li> Added support for
- <a href="http://daringfireball.net/projects/markdown/">Markdown</a>
+ <a href="https://daringfireball.net/projects/markdown/">Markdown</a>
formatting.
This is enabled by default, but can be disabled by
setting MARKDOWN_SUPPORT to NO. When enabled the following is
diff --git a/doc/commands.doc b/doc/commands.doc
index beda764..f04b543 100644
--- a/doc/commands.doc
+++ b/doc/commands.doc
@@ -106,6 +106,8 @@ documentation:
\refitem cmdheaderfile \\headerfile
\refitem cmdhidecallergraph \\hidecallergraph
\refitem cmdhidecallgraph \\hidecallgraph
+\refitem cmdhiderefby \\hiderefby
+\refitem cmdhiderefs \\hiderefs
\refitem cmdhideinitializer \\hideinitializer
\refitem cmdhtmlinclude \\htmlinclude
\refitem cmdhtmlonly \\htmlonly
@@ -174,6 +176,8 @@ documentation:
\refitem cmdsee \\see
\refitem cmdshort \\short
\refitem cmdshowinitializer \\showinitializer
+\refitem cmdshowrefby \\showrefby
+\refitem cmdshowrefs \\showrefs
\refitem cmdsince \\since
\refitem cmdskip \\skip
\refitem cmdskipline \\skipline
@@ -214,6 +218,7 @@ documentation:
\refitem cmdperc \\\%
\refitem cmdquot \\\"
\refitem cmdchardot \\\.
+\refitem cmdcolon \:
\refitem cmddcolon \::
\refitem cmdpipe \\|
\refitem cmdndash \\\--
@@ -306,7 +311,7 @@ Structural indicators
When this command is put in a comment block of a function or method
and \ref cfg_have_dot "HAVE_DOT" is set to \c YES, then doxygen will
generate a caller graph for that function (provided the implementation of the
- function or method calls other documented functions). The caller graph will be
+ function or method is called by other documented functions). The caller graph will be
generated regardless of the value of \ref cfg_caller_graph "CALLER_GRAPH".
\note The completeness (and correctness) of the caller graph depends on the
doxygen code parser which is not perfect.
@@ -333,6 +338,74 @@ Structural indicators
option \ref cfg_caller_graph "CALLER_GRAPH"
<hr>
+\section cmdshowrefby \\showrefby
+
+ \addindex \\showrefby
+ When this command is put in a comment block of a function, method or variable,
+ then doxygen will generate an overview for that function, method, variable of
+ the, documented, funcions and methods that call / use it.
+ The overview will be generated regardless of the value of
+ \ref cfg_referenced_by_relation "REFERENCED_BY_RELATION".
+ \note The completeness (and correctness) of the overview depends on the
+ doxygen code parser which is not perfect.
+
+ \sa section \ref cmdshowrefs "\\showrefs",
+ section \ref cmdhiderefby "\\hiderefby",
+ section \ref cmdhiderefs "\\hiderefs" and
+ option \ref cfg_referenced_by_relation "REFERENCED_BY_RELATION"
+
+<hr>
+\section cmdhiderefby \\hiderefby
+
+ \addindex \\hiderefby
+ When this command is put in a comment block of a function, method or variable
+ then doxygen will not generate an overview for that function, method or
+ variable of the functions and methods that call / use it.
+ The overview will not be generated regardless of the value of
+ \ref cfg_referenced_by_relation "REFERENCED_BY_RELATION".
+ \note The completeness (and correctness) of the overview depends on the
+ doxygen code parser which is not perfect.
+
+ \sa section \ref cmdshowrefs "\\showrefs",
+ section \ref cmdshowrefby "\\showrefby",
+ section \ref cmdhiderefs "\\hiderefs" and
+ option \ref cfg_referenced_by_relation "REFERENCED_BY_RELATION"
+
+<hr>
+\section cmdshowrefs \\showrefs
+
+ \addindex \\showrefs
+ When this command is put in a comment block of a function or method,
+ then doxygen will generate an overview for that function or method of the
+ functions and methods that call it.
+ The overview will be generated regardless of the value of
+ \ref cfg_references_relation "REFERENCES_RELATION".
+ \note The completeness (and correctness) of the overview depends on the
+ doxygen code parser which is not perfect.
+
+ \sa section \ref cmdshowrefby "\\showrefby",
+ section \ref cmdhiderefby "\\hiderefby",
+ section \ref cmdhiderefs "\\hiderefs" and
+ option \ref cfg_references_relation "REFERENCES_RELATION"
+
+<hr>
+\section cmdhiderefs \\hiderefs
+
+ \addindex \\hiderefs
+ When this command is put in a comment block of a function or method
+ and then doxygen will not generate an overview for that function or method of
+ the functions and methods that call it.
+ The overview will not be generated regardless of the value of
+ \ref cfg_references_relation "REFERENCES_RELATION".
+ \note The completeness (and correctness) of the overview depends on the
+ doxygen code parser which is not perfect.
+
+ \sa section \ref cmdshowrefs "\\showrefs",
+ section \ref cmdshowrefby "\\showrefby",
+ section \ref cmdhiderefby "\\hiderefby" and
+ option \ref cfg_references_relation "REFERENCES_RELATION"
+
+<hr>
\section cmdcategory \\category <name> [<header-file>] [<header-name>]
\addindex \\category
@@ -1888,7 +1961,7 @@ Commands to create links
\section cmdaddindex \\addindex (text)
\addindex \\addindex
- This command adds (text) to the \LaTeX index.
+ This command adds (text) to the \LaTeX , DocBook and RTF index.
<hr>
\section cmdanchor \\anchor <word>
@@ -2608,7 +2681,7 @@ only copy the detailed documentation, not the brief description.
\addindex \\docbookonly
Starts a block of text that will be verbatim included in the
- generated docbook documentation only. The block ends with a
+ generated DocBook documentation only. The block ends with a
\ref cmdenddocbookonly "\\enddocbookonly" command.
\sa section \ref cmdmanonly "\\manonly",
@@ -3057,7 +3130,7 @@ class Receiver
\ref cmddocbookonly "\\docbookonly".
<hr>
-\section cmdimage \\image <format> <file> ["caption"] [<sizeindication>=<size>]
+\section cmdimage \\image['{'[option]'}'] <format> <file> ["caption"] [<sizeindication>=<size>]
\addindex \\image
Inserts an image into the documentation. This command is format
@@ -3082,13 +3155,17 @@ class Receiver
spaces. The quotes are stripped before the caption is displayed.
The fourth argument is also optional and can be used to specify the
- width or height of the image. This can be useful for \LaTeX or docbook output
+ width or height of the image. This can be useful for \LaTeX or DocBook output
(i.e. format=<code>latex</code> or format=<code>docbook</code>).
\anchor image_sizeindicator \par Size indication
The \c sizeindication can specify the width or height to be used (or a combination).
The size specifier in \LaTeX (for example `10cm` or
`4in` or a symbolic width like `\\textwidth`).
+ Currently only the option `inline` is supported. In case the option `inline` is
+ specified the image is placed "in the line", when a caption s present it is shown
+ in HTML as tooltip (ignored for the other formats).
+
Here is example of a comment block:
\verbatim
@@ -3280,7 +3357,7 @@ class Receiver
\addindex \\\@
This command writes an at-sign (\c \@) to the output.
The at-sign has to be escaped in some cases
- because doxygen uses it to detect JavaDoc commands.
+ because doxygen uses it to detect Javadoc commands.
<hr>
\section cmdtilde \\~[LanguageId]
@@ -3362,6 +3439,14 @@ class Receiver
the start of a line.
<hr>
+\section cmdcolon \:
+
+ \addindex \\:
+ This command writes a single colon (\c \:) to the output. This
+ character sequence has to be escaped in some cases, because it is used
+ to define `emoji` see also \ref emojisup "Emoji support".
+
+<hr>
\section cmddcolon \\::
\addindex \\::
@@ -3424,4 +3509,3 @@ Go to the <a href="htmlcmds.html">next</a> section or return to the
\endhtmlonly
*/
-
diff --git a/doc/docblocks.doc b/doc/docblocks.doc
index f02e55b..a9cb05a 100644
--- a/doc/docblocks.doc
+++ b/doc/docblocks.doc
@@ -55,7 +55,7 @@ used to provide tooltips at places where an item is referenced.
There are several ways to mark a comment block as a detailed description:
<ol>
-<li> You can use the JavaDoc style, which consist of a C-style comment
+<li> You can use the Javadoc style, which consist of a C-style comment
block starting with two *'s, like this:
\verbatim
@@ -143,7 +143,7 @@ Here is an example:
<li>If \ref cfg_javadoc_autobrief "JAVADOC_AUTOBRIEF" is set to \c YES
in the configuration file,
- then using JavaDoc style comment
+ then using Javadoc style comment
blocks will automatically start a brief description which ends at the
first dot followed by a space or new line. Here is an example:
@@ -299,8 +299,8 @@ sentence of the detailed descriptions
tag to \c NO). Both the brief and the detailed descriptions are optional
for the Qt style.
-By default a JavaDoc style documentation block behaves the same way as a
-Qt style documentation block. This is not according the JavaDoc specification
+By default a Javadoc style documentation block behaves the same way as a
+Qt style documentation block. This is not according the Javadoc specification
however, where the first sentence of the documentation block is automatically
treated as a brief description. To enable this behavior you should set
\ref cfg_javadoc_autobrief "JAVADOC_AUTOBRIEF" to YES in the configuration
@@ -312,7 +312,7 @@ Here is an example:
\endverbatim
Here is the same piece of code as shown above, this time documented using the
-JavaDoc style and \ref cfg_javadoc_autobrief "JAVADOC_AUTOBRIEF" set to YES:
+Javadoc style and \ref cfg_javadoc_autobrief "JAVADOC_AUTOBRIEF" set to YES:
\include jdstyle.cpp
\htmlonly
</p>
@@ -348,7 +348,7 @@ duplication of information. So in practice you should \e avoid the use of
structural commands \e unless other requirements force you to do so.
Structural commands (like \ref cmd_intro "all other commands") start with a backslash
-(<tt>\\</tt>), or an at-sign (<tt>\@</tt>) if you prefer JavaDoc style,
+(<tt>\\</tt>), or an at-sign (<tt>\@</tt>) if you prefer Javadoc style,
followed by a command name and one or more parameters.
For instance, if you want to document the class \c Test in the example
above, you could have also put the following documentation block somewhere
@@ -632,7 +632,7 @@ and is ideal for a short description.
For longer descriptions you often will find the
need for some more structure, like a block of verbatim text, a list, or a
simple table. For this doxygen supports the
-<a href="http://daringfireball.net/projects/markdown/syntax">Markdown</a>
+<a href="https://daringfireball.net/projects/markdown/syntax">Markdown</a>
syntax, including parts of the
<a href="https://michelf.ca/projects/php-markdown/extra/">Markdown Extra</a>
extension.
@@ -648,8 +648,9 @@ forms of additional markup on top of Markdown formatting.
1. <a href="https://en.wikipedia.org/wiki/Javadoc">Javadoc</a> like markup.
See \ref commands for a complete overview of all commands supported by doxygen.
-2. <a href="https://en.wikipedia.org/wiki/C_Sharp_(programming_language)#XML_documentation_system">XML</a> markup
- as specified in the C# standard. See \ref xmlcmds for the XML commands supported by doxygen.
+2. <a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/xmldoc/recommended-tags-for-documentation-comments">XML</a> markup
+ as specified in the <a href="http://standards.iso.org/ittf/PubliclyAvailableStandards/c042926_ISO_IEC_23270_2006(E).zip">C# standard</a>.
+ See \ref xmlcmds for the XML commands supported by doxygen.
If this is still not enough doxygen also supports a \ref htmlcmds "subset" of
the <a href="https://en.wikipedia.org/wiki/HTML">HTML</a> markup language.
diff --git a/doc/doxygen_manual.tex b/doc/doxygen_manual.tex
index 95e1ed6..6ff089c 100644
--- a/doc/doxygen_manual.tex
+++ b/doc/doxygen_manual.tex
@@ -96,21 +96,21 @@ Written by Dimitri van Heesch\\[2ex]
\part{User Manual}
\chapter{Introduction}\label{intro}\hypertarget{intro}{}\input{index}
\chapter{Installation}\label{install}\hypertarget{install}{}\input{install}
-\chapter{Getting Started}\label{starting}\hypertarget{starting}{}\input{starting}
+\chapter{Getting started}\label{starting}\hypertarget{starting}{}\input{starting}
\chapter{Documenting the code}\label{docblocks}\hypertarget{docblocks}{}\input{docblocks}
-\chapter{Markdown}\label{markdown}\hypertarget{markdown}{}\input{markdown}
+\chapter{Markdown support}\label{markdown}\hypertarget{markdown}{}\input{markdown}
\chapter{Lists}\label{lists}\hypertarget{lists}{}\input{lists}
\chapter{Grouping}\label{grouping}\hypertarget{grouping}{}\input{grouping}
-\chapter{Including Formulas}\label{formulas}\hypertarget{formulas}{}\input{formulas}
-\chapter{Including Tables}\label{tables}\hypertarget{tables}{}\input{tables}
+\chapter{Including formulas}\label{formulas}\hypertarget{formulas}{}\input{formulas}
+\chapter{Including tables}\label{tables}\hypertarget{tables}{}\input{tables}
\chapter{Graphs and diagrams}\label{diagrams}\hypertarget{diagrams}{}\input{diagrams}
\chapter{Preprocessing}\label{preprocessing}\hypertarget{preprocessing}{}\input{preprocessing}
\chapter{Automatic link generation}\label{autolink}\hypertarget{autolink}{}\input{autolink}
\chapter{Output Formats}\label{output}\hypertarget{output}{}\input{output}
\chapter{Searching}\label{searching}\hypertarget{searching}{}\input{searching}
-\chapter{Customizing the Output}\label{customize}\hypertarget{customize}{}\input{customize}
-\chapter{Custom Commands}\label{custcmd}\hypertarget{custcmd}{}\input{custcmd}
-\chapter{Link to external documentation}\label{external}\hypertarget{external}{}\input{external}
+\chapter{Customizing the output}\label{customize}\hypertarget{customize}{}\input{customize}
+\chapter{Custom commands}\label{custcmd}\hypertarget{custcmd}{}\input{custcmd}
+\chapter{Linking to external documentation}\label{external}\hypertarget{external}{}\input{external}
\chapter{Frequently Asked Questions}\label{faq}\hypertarget{faq}{}\input{faq}
\chapter{Troubleshooting}\label{trouble}\hypertarget{trouble}{}\input{trouble}
\part{Reference Manual}
@@ -119,12 +119,13 @@ Written by Dimitri van Heesch\\[2ex]
\chapter{Doxywizard usage}\label{doxywizard_usage}\hypertarget{doxywizard_usage}{}\input{doxywizard_usage}
\chapter{Configuration}\label{config}\hypertarget{config}{}\input{config}
\chapter{Special Commands}\label{commands}\hypertarget{commands}{}\input{commands}
-\chapter{HTML commands}\label{htmlcmds}\hypertarget{htmlcmds}{}\input{htmlcmds}
-\chapter{XML commands}\label{xmlcmds}\hypertarget{xmlcmds}{}\input{xmlcmds}
+\chapter{HTML Commands}\label{htmlcmds}\hypertarget{htmlcmds}{}\input{htmlcmds}
+\chapter{XML Commands}\label{xmlcmds}\hypertarget{xmlcmds}{}\input{xmlcmds}
+\chapter{Emoji support}\label{emojisup}\hypertarget{emojisup}{}\input{emojisup}
\part{Developers Manual}
-\chapter{Doxygen's internals}\label{arch}\hypertarget{arch}{}\input{arch}
-\chapter{Perl Module Output format}\label{perlmod}\hypertarget{perlmod}{}\input{perlmod}
\chapter{Internationalization}\label{langhowto}\hypertarget{langhowto}{}\input{langhowto}
+\chapter{Perl Module Output}\label{perlmod}\hypertarget{perlmod}{}\input{perlmod}
+\chapter{Doxygen's internals}\label{arch}\hypertarget{arch}{}\input{arch}
\renewcommand{\thepart}{}
\part{Appendices}
\appendix
diff --git a/doc/emojisup.doc b/doc/emojisup.doc
new file mode 100644
index 0000000..75a90fb
--- /dev/null
+++ b/doc/emojisup.doc
@@ -0,0 +1,166 @@
+/******************************************************************************
+ *
+ *
+ *
+ * Copyright (C) 1997-2018 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.
+ *
+ */
+/*! \page emojisup Emoji support
+
+The [Unicode consortium](http://www.unicode.org/) has defined a set of
+[emoji](https://en.wikipedia.org/wiki/Emoji) with the corresponding unicode
+sequences and a so called "CLDR short name". The current version a v11.0 and can be found at
+[Full Emoji List, v11.0](https://unicode.org/emoji/charts/full-emoji-list.html) furthermore there is the list with
+[Full Emoji Modifier Sequences, v11.0](http://www.unicode.org/emoji/charts/full-emoji-modifiers.html).
+
+A common way to denote an emoji is by means of `:<text>:`,
+doxygen supports the emoji as mentioned in the above mentioned unicode emoji lists in this way
+by means of the "CLDR short name" with the exception that in case a colon (`:`) is in the
+"CLDR short name" this colon has to be removed.
+Furthermore doxygen supports the list of emoji as used by github (based on the list
+https://api.github.com/emojis). In this list also a reference is given to the unicode codes (just the
+first and last) and these unicodes are mapped onto the official unicode sequences.
+In case the "CLDR short name" and the "github name" are the same the reference from the
+"CLDR short name" has precedence.
+
+Implementation
+
+For the different doxygen output types there is an output defined:
+- Unicode code sequence, the actual representation is depending on the possibilities of the fonts loaded:
+ - HTML
+ - XML
+ - DocBook
+ - RTF, converted to UTF-16 representation.
+- Image
+ - \LaTeX, in case the image can be found (see \ref emojiimage "Emoji image retrieval") otherwise the plain emoji text (i.e. `:<text>:`) is displayed
+- plain emoji text (i.e. `:<text>:`)
+ - man
+ - perl
+
+\anchor emojiimage Emoji image retrieval
+
+In the lists
+[Full Emoji List, v11.0](https://unicode.org/emoji/charts/full-emoji-list.html) and
+[Full Emoji Modifier Sequences, v11.0](http://www.unicode.org/emoji/charts/full-emoji-modifiers.html).
+define images for the different vendors. These images can be retrieved by means of the following procedure (based on the code from Henning Pohl, https://github.com/henningpohl/latex-emoji):
+\code{.py}
+from bs4 import BeautifulSoup
+import base64
+import os
+import requests
+
+# http://www.unicode.org/emoji/charts/index.html
+# http://www.unicode.org/emoji/charts/full-emoji-list.html
+PAGE_URL = 'http://www.unicode.org/emoji/charts/full-emoji-list.html'
+PAGE_URL_SKIN = 'http://www.unicode.org/emoji/charts/full-emoji-modifiers.html'
+PAGE = 'full-emoji-list.html'
+PAGE_SKIN = 'full-emoji-modifiers.html'
+
+
+def get_header_names(header):
+ cols = header.find_all('th')
+ cols = [c.get_text() for c in cols]
+ cols = [c.replace('*','') for c in cols]
+ cols = [c.lower() for c in cols]
+ return cols
+
+def extract_image(column):
+ if 'miss' in column['class']:
+ return None
+
+ if 'miss7' in column['class']:
+ return None
+
+ data = column.img['src']
+ data_start = data.find("base64,")
+ if data_start == -1:
+ return None
+
+ data = base64.b64decode(data[data_start + len("base64,"):])
+ return data
+
+def save_image(folder, imgSrc, filename):
+ if os.path.exists(folder) is False:
+ os.mkdir(folder)
+
+ filename = os.path.join(folder, filename)
+ if os.path.exists(filename):
+ return
+
+ img = extract_image(imgSrc)
+ if img is not None:
+ with open(filename, 'wb') as out:
+ out.write(img)
+
+def scrape(page_url, page):
+ # Possibilities to obtain the basic data:
+ # - use request.get directly
+ soup = BeautifulSoup(requests.get(page_url).text, "html5lib")
+ # - download file (e.g. with wget http://www.unicode.org/emoji/charts/full-emoji-list.html)
+ # with open(page) as fp:
+ # soup = BeautifulSoup(fp,"html5lib")
+
+ table = soup('table')[0]
+
+ # for version 11.0
+ # first row: smileys
+ # second row: face smileys
+ # third row: row with vendors, i.e. the one we want
+ header = table.find_all('tr')[2]
+ keys = get_header_names(header)
+
+ for row in header.find_next_siblings('tr'):
+ fields = {k:c for k, c in zip(keys, row.find_all('td')) }
+ if 'code' not in fields:
+ continue
+
+ codes = fields['code'].text.replace('U+', '').split(' ')
+ filename = "-".join(codes) + ".png"
+
+ save_image('ios', fields['appl'], filename)
+ save_image('android', fields['goog'], filename)
+ save_image('twitter', fields['twtr'], filename)
+ save_image('windows', fields['wind'], filename)
+ save_image('one', fields['one'], filename)
+ save_image('facebook', fields['fb'], filename)
+ save_image('samsung', fields['sams'], filename)
+ #save_image('gmail', fields['gmail'], filename)
+ #save_image('softbank', fields['sb'], filename)
+ #save_image('docomo', fields['dcm'], filename)
+ #save_image('kddi', fields['kddi'], filename)
+ #save_image('bw', fields['chart'], filename)
+
+if __name__ == '__main__':
+ scrape(PAGE_URL, PAGE)
+ scrape(PAGE_URL_SKIN, PAGE_SKIN)
+\endcode
+This results in a number of directories with the supported images. By means of the doxygen configuration parameter
+\ref cfg_latex_emoji_directory "LATEX_EMOJI_DIRECTORY" the requested directory can be selected.
+
+It is also possible to use images from other sources or mix images from different sources, the only requirement is that the filename represents the unicode of the emoji. e.g. if we have the emoji <tt>\:grinning face with big eyes\:</tt> (also known as <tt>\:smiley\:</tt>) the coresponding unicode is `U+1F603` and the name of the file is `1F603.png`.<br>
+For a more complex emoji like <tt>\:keycap 1\:</tt> (also known as <tt>\:one\:</tt>) the coresponding unicode sequence is `U+0031U+FE0FU+20E3` and the name of the file is `0031-FE0F-20E3.png`.
+
+
+Note that when you want to use a colon (`:`) in your text it might be necessary to escape the colon (see \ref cmdcolon "\\:") as it might conflict with a, possible, emoji sequence.
+
+
+For a overview of the supported emoji one can issue the comand:<br>
+`doxygen.exe -f emoji <outputFileName>`
+
+
+\htmlonly
+Go to the <a href="langhowto.html">next</a> section or return to the
+ <a href="index.html">index</a>.
+\endhtmlonly
+
+*/
+
diff --git a/doc/features.doc b/doc/features.doc
index f6aa7c1..8b19898 100644
--- a/doc/features.doc
+++ b/doc/features.doc
@@ -33,7 +33,7 @@
<li>Supports documentation of files, namespaces, packages, classes,
structs, unions, templates, variables, functions, typedefs, enums and
defines.
-<li>JavaDoc (1.1), qdoc3 (partially), and ECMA-334 (C# spec.) compatible.
+<li>Javadoc (1.1), qdoc3 (partially), and ECMA-334 (C# spec.) compatible.
<li>Comes with a GUI frontend (Doxywizard) to ease editing the options and
run doxygen. The GUI is available on Windows, Linux, and MacOSX.
<li>Automatically generates class and collaboration diagrams in HTML (as clickable
@@ -100,7 +100,7 @@
Although doxygen can now be used in any project written in a language that is
supported by doxygen, initially it was specifically designed to be used for projects
that make use of Qt Software's
-<A HREF="http://qt-project.org/">Qt toolkit</A>. I have tried to
+<A HREF="https://www.qt.io/developers/">Qt toolkit</A>. I have tried to
make doxygen `Qt-compatible'. That is: Doxygen can read the documentation contained in
the Qt source code and create a class browser that looks quite similar to the
one that is generated by Qt Software. Doxygen understands the C++ extensions
diff --git a/doc/index.doc b/doc/index.doc
index b8f6e8e..9afe624 100644
--- a/doc/index.doc
+++ b/doc/index.doc
@@ -102,6 +102,8 @@ The second part forms a reference manual:
can be used within the documentation.
<li>Section \ref xmlcmds shows an overview of the C# style XML commands that
can be used within the documentation.
+<li>Section \ref emojisup shows an introduction how emoji can be used within
+ the documentation.
</ul>
The third part provides information for developers:
diff --git a/doc/install.doc b/doc/install.doc
index 7df0dee..d64b259 100644
--- a/doc/install.doc
+++ b/doc/install.doc
@@ -47,7 +47,7 @@ tools should be installed.
<ul>
<li>Qt Software's GUI toolkit
- <a href="http://qt-project.org/">Qt</A>
+ <a href="https://www.qt.io/developers/">Qt</A>
\addindex Qt
version 4.3 or higher (including Qt 5).
This is needed to build the GUI front-end doxywizard.
@@ -211,12 +211,12 @@ If you want to produce compressed HTML files (see \ref
cfg_generate_htmlhelp "GENERATE_HTMLHELP") in the configuration file, then
you need the Microsoft HTML help workshop.
You can download it from
-<a href="http://www.microsoft.com/en-us/download/details.aspx?id=21138">Microsoft</a>.
+<a href="https://www.microsoft.com/en-us/download/details.aspx?id=21138">Microsoft</a>.
If you want to produce Qt Compressed Help files (see \ref
cfg_qhg_location "QHG_LOCATION") in the configuration file, then
you need qhelpgenerator which is part of Qt.
-You can download Qt from <a href="http://qt-project.org/downloads">Qt Software Downloads</a>.
+You can download Qt from <a href="https://www.qt.io/download">Qt Software Downloads</a>.
In order to generate PDF output or use scientific formulas you will also need to
install <a href="https://en.wikipedia.org/wiki/LaTeX">LaTeX</a> and
diff --git a/doc/markdown.doc b/doc/markdown.doc
index 92612ca..5edbaf9 100644
--- a/doc/markdown.doc
+++ b/doc/markdown.doc
@@ -41,7 +41,7 @@ the extensions that doxygen supports.
Finally section \ref markdown_dox discusses some specifics for doxygen's
implementation of the Markdown standard.
-[markdown]: http://daringfireball.net/projects/markdown/
+[markdown]: https://daringfireball.net/projects/markdown/
[mdextra]: https://michelf.ca/projects/php-markdown/extra/
[github]: https://github.github.com/github-flavored-markdown/
@@ -173,7 +173,18 @@ Examples:
* __double underscores__
See section \ref mddox_emph_spans for more info how doxygen handles
-emphasis spans slightly different than standard Markdown.
+emphasis / strikethrough spans slightly different than standard / Markdown GitHub Flavored Markdown.
+
+\subsection md_strikethrough Strikethrough
+
+To strikethrough a text fragment you start and end the fragment with two tildes.
+
+Examples:
+
+* ~~double tilde~~
+
+See section \ref mddox_emph_spans for more info how doxygen handles
+emphasis / strikethrough spans slightly different than standard Markdown / GitHub Flavored Markdown.
\subsection md_codespan code spans
@@ -567,22 +578,22 @@ For Item1 the indentation is 4 (when treating the list marker as whitespace),
so the next paragraph "More text..." starts at the same indentation level
and is therefore not seen as a code block.
-\subsection mddox_emph_spans Emphasis limits
+\subsection mddox_emph_spans Emphasis and strikethrough limits
-Unlike standard Markdown, doxygen will not touch internal underscores or
-stars, so the following will appear as-is:
+Unlike standard Markdown and Github Flavored Markdown doxygen will not touch internal underscores or
+stars or tildes, so the following will appear as-is:
a_nice_identifier
-Furthermore, a `*` or `_` only starts an emphasis if
+Furthermore, a `*` or `_` only starts an emphasis and a `~` only starts a strikethrough if
- it is followed by an alphanumerical character, and
- it is preceded by a space, newline, or one the following characters `<{([,:;`
-An emphasis ends if
+An emphasis or a strikethrough ends if
- it is not followed by an alphanumerical character, and
- it is not preceded by a space, newline, or one the following characters `({[<=+-\@`
-Lastly, the span of the emphasis is limited to a single paragraph.
+Lastly, the span of the emphasis or strikethrough is limited to a single paragraph.
\subsection mddox_code_spans Code Spans Limits
diff --git a/doc/output.doc b/doc/output.doc
index 3a24a60..6d1a567 100644
--- a/doc/output.doc
+++ b/doc/output.doc
@@ -32,7 +32,7 @@ The following output formats are \e directly supported by doxygen:
Word. If you have success with other programs, please let me know.
<dt><b>XML</b>
<dd>Generated if \ref cfg_generate_xml "GENERATE_XML" is set to \c YES in the configuration file.<p>
-<dt><b>Docbook</b>
+<dt><b>DocBook</b>
<dd>Generated if \ref cfg_generate_docbook "GENERATE_DOCBOOOK" is set to \c YES in the configuration file.<p>
</dl>
diff --git a/doc/perlmod.doc b/doc/perlmod.doc
index 3d2e2c2..1ef4bbc 100644
--- a/doc/perlmod.doc
+++ b/doc/perlmod.doc
@@ -56,7 +56,7 @@ Perl and it's the main purpose of including the Perl Module backend in
doxygen. See \ref doxydocs_format "below" for details on how
to do this.
-<-- want to use \LaTeX but not possible in headings -->
+<!-- want to use \LaTeX but not possible in headings -->
\section perlmod_latex Using the LaTeX generator.
<p>The Perl Module-based \LaTeX generator is pretty experimental and
diff --git a/doc/searching.doc b/doc/searching.doc
index cb6b84a..9bc518a 100644
--- a/doc/searching.doc
+++ b/doc/searching.doc
@@ -126,7 +126,7 @@ has its own advantages and disadvantages:
options you may want to set. After doxygen has finished you will find
a Makefile in the HTML output directory. Running "make install" on this
Makefile will compile and install the doc set.
- See <a href="https://developer.apple.com/library/mac/#featuredarticles/DoxygenXcode/_index.html">this
+ See <a href="https://developer.apple.com/library/archive/featuredarticles/DoxygenXcode/_index.html">this
article</a> for more info.
Advantage of this method is that it nicely integrates with the Xcode
@@ -139,7 +139,7 @@ has its own advantages and disadvantages:
<h2>6. Qt Compressed Help</h2>
If you develop for or want to install the Qt application framework,
you will get an application
- called <a href="http://qt-project.org/doc/qt-4.8/assistant-manual.html">Qt assistant</a>.
+ called <a href="http://doc.qt.io/archives/qt-4.8/assistant-manual.html">Qt assistant</a>.
This is a help viewer for Qt Compressed Help files (<code>.qch</code>).
To enable this feature set \ref cfg_generate_qhp "GENERATE_QHP" to \c YES.
diff --git a/doc/starting.doc b/doc/starting.doc
index 0765a3b..64d3be0 100644
--- a/doc/starting.doc
+++ b/doc/starting.doc
@@ -263,7 +263,7 @@ capabilities of the man page format, so some information
\subsection docbook_out DocBook output
\addindex docbook
Doxygen can also generate output in the
-<a href="http://docbook.org/">DocBook</a> format. How to process the
+<a href="https://docbook.org/">DocBook</a> format. How to process the
DocBook output is beyond the scope of this manual.
\section step3 Step 3: Documenting the sources
diff --git a/doc/translator.py b/doc/translator.py
index 798774b..2246c08 100644
--- a/doc/translator.py
+++ b/doc/translator.py
@@ -1226,12 +1226,20 @@ class TrManager:
doxy_default = os.path.join(self.script_path, '..')
self.doxy_path = os.path.abspath(os.getenv('DOXYGEN', doxy_default))
- # Get the explicit arguments of the script.
- self.script_argLst = sys.argv[1:]
-
# Build the path names based on the Doxygen's root knowledge.
self.doc_path = os.path.join(self.doxy_path, 'doc')
self.src_path = os.path.join(self.doxy_path, 'src')
+ # Normally the original sources aren't in the current directory
+ # (as we are in the build directory) so we have to specify the
+ # original source directory.
+ self.org_src_path = self.src_path
+ if (len(sys.argv) > 1 and os.path.isdir(os.path.join(sys.argv[1], 'src'))):
+ self.org_src_path = os.path.join(sys.argv[1], 'src')
+ # Get the explicit arguments of the script.
+ self.script_argLst = sys.argv[2:]
+ else:
+ # Get the explicit arguments of the script.
+ self.script_argLst = sys.argv[1:]
# Create the empty dictionary for Transl object identified by the
# class identifier of the translator.
@@ -1413,15 +1421,15 @@ class TrManager:
are searched in doxygen/src directory.
"""
files = []
- for item in os.listdir(self.src_path):
+ for item in os.listdir(self.org_src_path):
# Split the bare name to get the extension.
name, ext = os.path.splitext(item)
ext = ext.lower()
# Include only .cpp and .h files (case independent) and exclude
# the files where the checked identifiers are defined.
- if ext == '.cpp' or (ext == '.h' and name.find('translator') == -1):
- fname = os.path.join(self.src_path, item)
+ if ext == '.cpp' or ext == '.l' or (ext == '.h' and name.find('translator') == -1):
+ fname = os.path.join(self.org_src_path, item)
assert os.path.isfile(fname) # assumes no directory with the ext
files.append(fname) # full name
return files
@@ -1444,12 +1452,14 @@ class TrManager:
assert os.path.isfile(fname)
f = xopen(fname)
cont = f.read()
+ cont = ''.join(cont.split('\n')) # otherwise the 'match' function won't work.
f.close()
# Remove the items for identifiers that were found in the file.
while lst_in:
item = lst_in.pop(0)
- if cont.find(item) != -1:
+ rexItem = re.compile('.*' + item + ' *\(')
+ if rexItem.match(cont):
del dic[item]
diff --git a/doc/xmlcmds.doc b/doc/xmlcmds.doc
index 848858d..b59095b 100644
--- a/doc/xmlcmds.doc
+++ b/doc/xmlcmds.doc
@@ -104,7 +104,7 @@ class Engine
\htmlonly
-Go to the <a href="langhowto.html">next</a> section or return to the
+Go to the <a href="emojisup.html">next</a> section or return to the
<a href="index.html">index</a>.
\endhtmlonly
diff --git a/examples/jdstyle.cfg b/examples/jdstyle.cfg
index 0ddc0d9..d94089d 100644
--- a/examples/jdstyle.cfg
+++ b/examples/jdstyle.cfg
@@ -1,4 +1,4 @@
-PROJECT_NAME = "JavaDoc Style"
+PROJECT_NAME = "Javadoc Style"
OUTPUT_DIRECTORY = ../html/examples/jdstyle
GENERATE_LATEX = YES
GENERATE_MAN = NO
diff --git a/libmd5/md5.c b/libmd5/md5.c
index 5210d92..d0627ff 100644
--- a/libmd5/md5.c
+++ b/libmd5/md5.c
@@ -189,7 +189,7 @@ MD5Final(md5byte digest[16], struct MD5Context *ctx)
void
MD5Transform(UWORD32 buf[4], UWORD32 const in[16])
{
- register UWORD32 a, b, c, d;
+ UWORD32 a, b, c, d;
a = buf[0];
b = buf[1];
diff --git a/qtools/qcstring.cpp b/qtools/qcstring.cpp
index 35b9bb8..77461b2 100644
--- a/qtools/qcstring.cpp
+++ b/qtools/qcstring.cpp
@@ -41,7 +41,7 @@ QCString &QCString::sprintf( const char *format, ... )
int QCString::find( char c, int index, bool cs ) const
{
if (index<0 || index>=(int)length()) return -1; // index outside string
- register const char *pos;
+ const char *pos;
if (cs)
{
pos = strchr(data()+index,c);
@@ -62,7 +62,7 @@ int QCString::find( const char *str, int index, bool cs ) const
if (index<0 || index>=l) return -1; // index outside string
if (!str) return -1; // no string to search for
if (!*str) return index; // empty string matching at index
- register const char *pos;
+ const char *pos;
if (cs) // case sensitive
{
pos = strstr(data()+index,str);
@@ -132,7 +132,7 @@ int QCString::findRev( const char *str, int index, bool cs) const
else if (index>len) return -1; // bad index
else if (index+slen>len) index=len-slen; // str would be too long
if (index<0) return -1; // no match possible
- register const char *pos = data()+index;
+ const char *pos = data()+index;
if (cs) // case sensitive
{
for (int i=index; i>=0; i--) if (qstrncmp(pos--,str,slen)==0) return i;
@@ -253,7 +253,7 @@ QCString QCString::mid( uint index, uint len) const
}
else
{
- register const char *p = data()+index;
+ const char *p = data()+index;
QCString s(len+1);
qstrncpy( s.rawData(), p, len+1 );
return s;
@@ -264,7 +264,7 @@ QCString QCString::lower() const
{
if (length()==0) return QCString();
QCString s(data());
- register char *pos = s.rawData();
+ char *pos = s.rawData();
if (pos)
{
while (*pos)
@@ -280,7 +280,7 @@ QCString QCString::upper() const
{
if (length()==0) return QCString();
QCString s(data());
- register char *pos = s.rawData();
+ char *pos = s.rawData();
if (pos)
{
while (*pos)
@@ -297,13 +297,13 @@ QCString QCString::stripWhiteSpace() const
if ( isEmpty() ) // nothing to do
return *this;
- register const char *cs = data();
+ const char *cs = data();
int reslen = length();
if ( !isspace((uchar)cs[0]) && !isspace((uchar)cs[reslen-1]) )
return *this; // returns a copy
QCString result(cs);
- register char *s = result.rawData();
+ char *s = result.rawData();
int start = 0;
int end = reslen - 1;
while ( isspace((uchar) s[start]) ) // skip white space from start
@@ -489,7 +489,7 @@ QCString &QCString::setNum(uint n)
QCString &QCString::setNum(long n)
{
char buf[20];
- register char *p = &buf[19];
+ char *p = &buf[19];
bool neg;
if ( n < 0 )
{
@@ -514,7 +514,7 @@ QCString &QCString::setNum(long n)
QCString &QCString::setNum( ulong n)
{
char buf[20];
- register char *p = &buf[19];
+ char *p = &buf[19];
*p = '\0';
do
{
@@ -529,8 +529,8 @@ QCString &QCString::setNum( ulong n)
void *qmemmove( void *dst, const void *src, uint len )
{
- register char *d;
- register char *s;
+ char *d;
+ char *s;
if ( dst > src ) {
d = (char *)dst + len - 1;
s = (char *)src + len - 1;
@@ -566,8 +566,8 @@ char *qstrncpy( char *dst, const char *src, uint len )
int qstricmp( const char *str1, const char *str2 )
{
- register const uchar *s1 = (const uchar *)str1;
- register const uchar *s2 = (const uchar *)str2;
+ const uchar *s1 = (const uchar *)str1;
+ const uchar *s2 = (const uchar *)str2;
int res;
uchar c;
if ( !s1 || !s2 )
@@ -580,8 +580,8 @@ int qstricmp( const char *str1, const char *str2 )
int qstrnicmp( const char *str1, const char *str2, uint len )
{
- register const uchar *s1 = (const uchar *)str1;
- register const uchar *s2 = (const uchar *)str2;
+ const uchar *s1 = (const uchar *)str1;
+ const uchar *s2 = (const uchar *)str2;
int res;
uchar c;
if ( !s1 || !s2 )
diff --git a/qtools/qdatastream.cpp b/qtools/qdatastream.cpp
index 70bcab1..5190b53 100644
--- a/qtools/qdatastream.cpp
+++ b/qtools/qdatastream.cpp
@@ -403,7 +403,7 @@ void QDataStream::setByteOrder( int bo )
static Q_INT32 read_int_ascii( QDataStream *s )
{
- register int n = 0;
+ int n = 0;
char buf[40];
while ( TRUE ) {
buf[n] = s->device()->getch();
@@ -462,7 +462,7 @@ QDataStream &QDataStream::operator>>( Q_INT16 &i )
} else if ( noswap ) { // no conversion needed
dev->readBlock( (char *)&i, sizeof(Q_INT16) );
} else { // swap bytes
- register uchar *p = (uchar *)(&i);
+ uchar *p = (uchar *)(&i);
char b[2];
dev->readBlock( b, 2 );
*p++ = b[1];
@@ -491,7 +491,7 @@ QDataStream &QDataStream::operator>>( Q_INT32 &i )
} else if ( noswap ) { // no conversion needed
dev->readBlock( (char *)&i, sizeof(Q_INT32) );
} else { // swap bytes
- register uchar *p = (uchar *)(&i);
+ uchar *p = (uchar *)(&i);
char b[4];
dev->readBlock( b, 4 );
*p++ = b[3];
@@ -521,7 +521,7 @@ QDataStream &QDataStream::operator>>( Q_INT64 &i )
} else if ( noswap ) { // no conversion needed
dev->readBlock( (char *)&i, sizeof(Q_INT64) );
} else { // swap bytes
- register uchar *p = (uchar *)(&i);
+ uchar *p = (uchar *)(&i);
char b[sizeof(Q_INT64)];
dev->readBlock( b, sizeof(Q_INT64) );
if ( sizeof(Q_INT64) == 8 ) {
@@ -540,7 +540,7 @@ QDataStream &QDataStream::operator>>( Q_INT64 &i )
static double read_double_ascii( QDataStream *s )
{
- register int n = 0;
+ int n = 0;
char buf[80];
while ( TRUE ) {
buf[n] = s->device()->getch();
@@ -566,7 +566,7 @@ QDataStream &QDataStream::operator>>( float &f )
} else if ( noswap ) { // no conversion needed
dev->readBlock( (char *)&f, sizeof(float) );
} else { // swap bytes
- register uchar *p = (uchar *)(&f);
+ uchar *p = (uchar *)(&f);
char b[4];
dev->readBlock( b, 4 );
*p++ = b[3];
@@ -591,7 +591,7 @@ QDataStream &QDataStream::operator>>( double &f )
} else if ( noswap ) { // no conversion needed
dev->readBlock( (char *)&f, sizeof(double) );
} else { // swap bytes
- register uchar *p = (uchar *)(&f);
+ uchar *p = (uchar *)(&f);
char b[8];
dev->readBlock( b, 8 );
*p++ = b[7];
@@ -670,7 +670,7 @@ QDataStream &QDataStream::readRawBytes( char *s, uint len )
{
CHECK_STREAM_PRECOND
if ( printable ) { // printable data
- register Q_INT8 *p = (Q_INT8*)s;
+ Q_INT8 *p = (Q_INT8*)s;
while ( len-- )
*this >> *p++;
} else { // read data char array
@@ -734,7 +734,7 @@ QDataStream &QDataStream::operator<<( Q_INT16 i )
} else if ( noswap ) { // no conversion needed
dev->writeBlock( (char *)&i, sizeof(Q_INT16) );
} else { // swap bytes
- register uchar *p = (uchar *)(&i);
+ uchar *p = (uchar *)(&i);
char b[2];
b[1] = *p++;
b[0] = *p;
@@ -765,7 +765,7 @@ QDataStream &QDataStream::operator<<( Q_INT32 i )
} else if ( noswap ) { // no conversion needed
dev->writeBlock( (char *)&i, sizeof(Q_INT32) );
} else { // swap bytes
- register uchar *p = (uchar *)(&i);
+ uchar *p = (uchar *)(&i);
char b[4];
b[3] = *p++;
b[2] = *p++;
@@ -797,7 +797,7 @@ QDataStream &QDataStream::operator<<( Q_INT64 i )
} else if ( noswap ) { // no conversion needed
dev->writeBlock( (char *)&i, sizeof(Q_INT64) );
} else { // swap bytes
- register uchar *p = (uchar *)(&i);
+ uchar *p = (uchar *)(&i);
char b[sizeof(Q_INT64)];
if ( sizeof(Q_INT64) == 8 ) {
b[7] = *p++;
@@ -845,7 +845,7 @@ QDataStream &QDataStream::operator<<( float f )
if ( noswap ) { // no conversion needed
dev->writeBlock( (char *)&g, sizeof(float) );
} else { // swap bytes
- register uchar *p = (uchar *)(&g);
+ uchar *p = (uchar *)(&g);
char b[4];
b[3] = *p++;
b[2] = *p++;
@@ -873,7 +873,7 @@ QDataStream &QDataStream::operator<<( double f )
} else if ( noswap ) { // no conversion needed
dev->writeBlock( (char *)&f, sizeof(double) );
} else { // swap bytes
- register uchar *p = (uchar *)(&f);
+ uchar *p = (uchar *)(&f);
char b[8];
b[7] = *p++;
b[6] = *p++;
@@ -939,7 +939,7 @@ QDataStream &QDataStream::writeRawBytes( const char *s, uint len )
{
CHECK_STREAM_PRECOND
if ( printable ) { // write printable
- register char *p = (char *)s;
+ char *p = (char *)s;
while ( len-- )
*this << *p++;
} else { // write data char array
diff --git a/qtools/qgarray.cpp b/qtools/qgarray.cpp
index df31363..2607a26 100644
--- a/qtools/qgarray.cpp
+++ b/qtools/qgarray.cpp
@@ -255,17 +255,17 @@ bool QGArray::fill( const char *d, int len, uint sz )
if ( sz == 1 ) // 8 bit elements
memset( data(), *d, len );
else if ( sz == 4 ) { // 32 bit elements
- register Q_INT32 *x = (Q_INT32*)data();
+ Q_INT32 *x = (Q_INT32*)data();
Q_INT32 v = *((Q_INT32*)d);
while ( len-- )
*x++ = v;
} else if ( sz == 2 ) { // 16 bit elements
- register Q_INT16 *x = (Q_INT16*)data();
+ Q_INT16 *x = (Q_INT16*)data();
Q_INT16 v = *((Q_INT16*)d);
while ( len-- )
*x++ = v;
} else { // any other size elements
- register char *x = data();
+ char *x = data();
while ( len-- ) { // more complicated
memcpy( x, d, sz );
x += sz;
@@ -329,7 +329,7 @@ QGArray &QGArray::duplicate( const QGArray &a )
if ( a.shd == shd ) { // a.duplicate(a) !
if ( shd->count > 1 ) {
shd->count--;
- register array_data *n = newData();
+ array_data *n = newData();
CHECK_PTR( n );
if ( (n->len=shd->len) ) {
n->data = NEW(char,n->len);
@@ -528,11 +528,11 @@ int QGArray::find( const char *d, uint index, uint sz ) const
#endif
return -1;
}
- register uint i;
+ uint i;
uint ii;
switch ( sz ) {
case 1: { // 8 bit elements
- register char *x = data() + index;
+ char *x = data() + index;
char v = *d;
for ( i=index; i<shd->len; i++ ) {
if ( *x++ == v )
@@ -542,7 +542,7 @@ int QGArray::find( const char *d, uint index, uint sz ) const
}
break;
case 2: { // 16 bit elements
- register Q_INT16 *x = (Q_INT16*)(data() + index);
+ Q_INT16 *x = (Q_INT16*)(data() + index);
Q_INT16 v = *((Q_INT16*)d);
for ( i=index; i<shd->len; i+=2 ) {
if ( *x++ == v )
@@ -552,7 +552,7 @@ int QGArray::find( const char *d, uint index, uint sz ) const
}
break;
case 4: { // 32 bit elements
- register Q_INT32 *x = (Q_INT32*)(data() + index);
+ Q_INT32 *x = (Q_INT32*)(data() + index);
Q_INT32 v = *((Q_INT32*)d);
for ( i=index; i<shd->len; i+=4 ) {
if ( *x++ == v )
@@ -583,11 +583,11 @@ int QGArray::find( const char *d, uint index, uint sz ) const
int QGArray::contains( const char *d, uint sz ) const
{
- register uint i = shd->len;
+ uint i = shd->len;
int count = 0;
switch ( sz ) {
case 1: { // 8 bit elements
- register char *x = data();
+ char *x = data();
char v = *d;
while ( i-- ) {
if ( *x++ == v )
@@ -596,7 +596,7 @@ int QGArray::contains( const char *d, uint sz ) const
}
break;
case 2: { // 16 bit elements
- register Q_INT16 *x = (Q_INT16*)data();
+ Q_INT16 *x = (Q_INT16*)data();
Q_INT16 v = *((Q_INT16*)d);
i /= 2;
while ( i-- ) {
@@ -606,7 +606,7 @@ int QGArray::contains( const char *d, uint sz ) const
}
break;
case 4: { // 32 bit elements
- register Q_INT32 *x = (Q_INT32*)data();
+ Q_INT32 *x = (Q_INT32*)data();
Q_INT32 v = *((Q_INT32*)d);
i /= 4;
while ( i-- ) {
diff --git a/qtools/qgcache.cpp b/qtools/qgcache.cpp
index 683c2a7..03150fe 100644
--- a/qtools/qgcache.cpp
+++ b/qtools/qgcache.cpp
@@ -577,7 +577,7 @@ bool QGCache::makeRoomFor( int cost, int priority )
return FALSE; // than maximum cost
if ( priority == -1 )
priority = 32767;
- register QCacheItem *ci = lruList->last();
+ QCacheItem *ci = lruList->last();
int cntCost = 0;
int dumps = 0; // number of items to dump
while ( cntCost < cost && ci && ci->skipPriority <= priority ) {
diff --git a/qtools/qgdict.cpp b/qtools/qgdict.cpp
index c8d8fbd..ab3fea9 100644
--- a/qtools/qgdict.cpp
+++ b/qtools/qgdict.cpp
@@ -90,7 +90,7 @@ int QGDict::hashKeyString( const QString &key )
qWarning( "QGDict::hashStringKey: Invalid null key" );
#endif
int i;
- register uint h=0;
+ uint h=0;
uint g;
int len = key.length();
const QChar *p = key.unicode();
@@ -129,8 +129,8 @@ int QGDict::hashKeyAscii( const char *key )
return 0;
}
#endif
- register const char *k = key;
- register uint h=0;
+ const char *k = key;
+ uint h=0;
uint g;
if ( cases ) { // case sensitive
while ( *k ) {
@@ -1170,8 +1170,8 @@ QCollection::Item QGDictIterator::toFirst()
curNode = 0;
return 0;
}
- register uint i = 0;
- register QBaseBucket **v = dict->vec;
+ uint i = 0;
+ QBaseBucket **v = dict->vec;
while ( !(*v++) )
i++;
curNode = dict->vec[i];
@@ -1217,8 +1217,8 @@ QCollection::Item QGDictIterator::operator++()
return 0;
curNode = curNode->getNext();
if ( !curNode ) { // no next bucket
- register uint i = curIndex + 1; // look from next vec element
- register QBaseBucket **v = &dict->vec[i];
+ uint i = curIndex + 1; // look from next vec element
+ QBaseBucket **v = &dict->vec[i];
while ( i < dict->size() && !(*v++) )
i++;
if ( i == dict->size() ) { // nothing found
diff --git a/qtools/qglist.cpp b/qtools/qglist.cpp
index 731d9fd..8197db5 100644
--- a/qtools/qglist.cpp
+++ b/qtools/qglist.cpp
@@ -280,7 +280,7 @@ QLNode *QGList::locate( uint index )
curNode = firstNode;
curIndex = 0;
}
- register QLNode *node;
+ QLNode *node;
int distance = index - curIndex; // node distance to cur node
bool forward; // direction to traverse
@@ -327,7 +327,7 @@ QLNode *QGList::locate( uint index )
void QGList::inSort( QCollection::Item d )
{
int index = 0;
- register QLNode *n = firstNode;
+ QLNode *n = firstNode;
while ( n && compareItems(n->data,d) < 0 ){ // find position in list
n = n->next;
index++;
@@ -343,7 +343,7 @@ void QGList::inSort( QCollection::Item d )
void QGList::prepend( QCollection::Item d )
{
- register QLNode *n = new QLNode( newItem(d) );
+ QLNode *n = new QLNode( newItem(d) );
CHECK_PTR( n );
n->prev = 0;
if ( (n->next = firstNode) ) // list is not empty
@@ -363,7 +363,7 @@ void QGList::prepend( QCollection::Item d )
void QGList::append( QCollection::Item d )
{
- register QLNode *n = new QLNode( newItem(d) );
+ QLNode *n = new QLNode( newItem(d) );
CHECK_PTR( n );
n->next = 0;
if ( (n->prev = lastNode) ) // list is not empty
@@ -394,7 +394,7 @@ bool QGList::insertAt( uint index, QCollection::Item d )
if ( !nextNode ) // illegal position
return FALSE;
QLNode *prevNode = nextNode->prev;
- register QLNode *n = new QLNode( newItem(d) );
+ QLNode *n = new QLNode( newItem(d) );
CHECK_PTR( n );
nextNode->prev = n;
prevNode->next = n;
@@ -437,7 +437,7 @@ QLNode *QGList::unlink()
{
if ( curNode == 0 ) // null current node
return 0;
- register QLNode *n = curNode; // unlink this node
+ QLNode *n = curNode; // unlink this node
if ( n == firstNode ) { // removing first node ?
if ( (firstNode = n->next) ) {
firstNode->prev = 0;
@@ -651,7 +651,7 @@ QCollection::Item QGList::takeLast()
void QGList::clear()
{
- register QLNode *n = firstNode;
+ QLNode *n = firstNode;
firstNode = lastNode = curNode = 0; // initialize list
numNodes = 0;
@@ -682,7 +682,7 @@ void QGList::clear()
int QGList::findRef( QCollection::Item d, bool fromStart )
{
- register QLNode *n;
+ QLNode *n;
int index;
if ( fromStart ) { // start from first node
n = firstNode;
@@ -707,7 +707,7 @@ int QGList::findRef( QCollection::Item d, bool fromStart )
int QGList::find( QCollection::Item d, bool fromStart )
{
- register QLNode *n;
+ QLNode *n;
int index;
if ( fromStart ) { // start from first node
n = firstNode;
@@ -733,7 +733,7 @@ int QGList::find( QCollection::Item d, bool fromStart )
uint QGList::containsRef( QCollection::Item d ) const
{
- register QLNode *n = firstNode;
+ QLNode *n = firstNode;
uint count = 0;
while ( n ) { // for all nodes...
if ( n->data == d ) // count # exact matches
@@ -750,7 +750,7 @@ uint QGList::containsRef( QCollection::Item d ) const
uint QGList::contains( QCollection::Item d ) const
{
- register QLNode *n = firstNode;
+ QLNode *n = firstNode;
uint count = 0;
QGList *that = (QGList*)this; // mutable for compareItems()
while ( n ) { // for all nodes...
@@ -876,7 +876,7 @@ void QGList::toVector( QGVector *vector ) const
vector->clear();
if ( !vector->resize( count() ) )
return;
- register QLNode *n = firstNode;
+ QLNode *n = firstNode;
uint i = 0;
while ( n ) {
vector->insert( i, n->data );
diff --git a/qtools/qgvector.cpp b/qtools/qgvector.cpp
index 63cce64..2d08ede 100644
--- a/qtools/qgvector.cpp
+++ b/qtools/qgvector.cpp
@@ -411,8 +411,8 @@ void QGVector::sort() // sort vector
{
if ( count() == 0 ) // no elements
return;
- register Item *start = &vec[0];
- register Item *end = &vec[len-1];
+ Item *start = &vec[0];
+ Item *end = &vec[len-1];
Item tmp;
while ( TRUE ) { // put all zero elements behind
while ( start < end && *start != 0 )
diff --git a/qtools/qstring.cpp b/qtools/qstring.cpp
index fe478bd..0e2b14a 100644
--- a/qtools/qstring.cpp
+++ b/qtools/qstring.cpp
@@ -12956,7 +12956,7 @@ int QString::find( QChar c, int index, bool cs ) const
index += length();
if ( (uint)index >= length() ) // index outside string
return -1;
- register const QChar *uc;
+ const QChar *uc;
uc = unicode()+index;
int n = length()-index;
if ( cs ) {
@@ -13325,7 +13325,7 @@ QString QString::mid( uint index, uint len ) const
len = slen - index;
if ( index == 0 && len == length() )
return *this;
- register const QChar *p = unicode()+index;
+ const QChar *p = unicode()+index;
QString s( len, TRUE );
memcpy( s.d->unicode, p, len*sizeof(QChar) );
s.d->len = len;
@@ -13429,7 +13429,7 @@ QString QString::lower() const
int l=length();
if ( l ) {
s.real_detach(); // could do this only when we find a change
- register QChar *p=s.d->unicode;
+ QChar *p=s.d->unicode;
if ( p ) {
while ( l-- ) {
*p = p->lower();
@@ -13458,7 +13458,7 @@ QString QString::upper() const
int l=length();
if ( l ) {
s.real_detach(); // could do this only when we find a change
- register QChar *p=s.d->unicode;
+ QChar *p=s.d->unicode;
if ( p ) {
while ( l-- ) {
*p = p->upper();
@@ -13493,7 +13493,7 @@ QString QString::stripWhiteSpace() const
if ( !at(0).isSpace() && !at(length()-1).isSpace() )
return *this;
- register const QChar *s = unicode();
+ const QChar *s = unicode();
QString result = fromLatin1("");
int start = 0;
diff --git a/qtools/qtextstream.cpp b/qtools/qtextstream.cpp
index 4ebf59e..ffbdeba 100644
--- a/qtools/qtextstream.cpp
+++ b/qtools/qtextstream.cpp
@@ -1596,7 +1596,7 @@ QTextStream &QTextStream::output_int( int format, ulong n, bool neg )
static char hexdigits_upper[] = "0123456789ABCDEF";
CHECK_STREAM_PRECOND
char buf[76];
- register char *p;
+ char *p;
int len;
char *hexdigits;
@@ -1784,7 +1784,7 @@ QTextStream &QTextStream::operator<<( double f )
f_char = (flags() & uppercase) ? 'E' : 'e';
else
f_char = (flags() & uppercase) ? 'G' : 'g';
- register char *fs = format; // generate format string
+ char *fs = format; // generate format string
*fs++ = '%'; // "%.<prec>l<f_char>"
*fs++ = '.';
int prec = precision();
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b57d360..4dc31fa 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -183,6 +183,7 @@ add_library(_doxygen STATIC
dot.cpp
doxygen.cpp
eclipsehelp.cpp
+ emoji.cpp
entry.cpp
filedef.cpp
filename.cpp
diff --git a/src/cite.cpp b/src/cite.cpp
index b17800f..4f88611 100644
--- a/src/cite.cpp
+++ b/src/cite.cpp
@@ -223,7 +223,6 @@ void CiteDict::generatePage() const
if (line.find("<!-- BEGIN BIBLIOGRAPHY")!=-1) insideBib=TRUE;
else if (line.find("<!-- END BIBLIOGRAPH")!=-1) insideBib=FALSE;
- else if (insideBib) doc+=line+"\n";
int i;
// determine text to use at the location of the @cite command
if (insideBib && (i=line.find("name=\"CITEREF_"))!=-1)
@@ -234,14 +233,17 @@ void CiteDict::generatePage() const
{
QCString label = line.mid(i+14,j-i-14);
QCString number = line.mid(j+2,k-j-1);
+ label = substitute(substitute(label,"&ndash;","--"),"&mdash;","---");
CiteInfo *ci = m_entries.find(label);
//printf("label='%s' number='%s' => %p\n",label.data(),number.data(),ci);
+ line = line.left(i+14) + label + line.right(line.length()-j);
if (ci)
{
ci->text = number;
}
}
}
+ if (insideBib) doc+=line+"\n";
}
//printf("doc=[%s]\n",doc.data());
diff --git a/src/classdef.cpp b/src/classdef.cpp
index 787cd5e..77d9e05 100644
--- a/src/classdef.cpp
+++ b/src/classdef.cpp
@@ -17,6 +17,7 @@
#include <stdio.h>
#include <qfile.h>
+#include <qfileinfo.h>
#include <qregexp.h>
#include "classdef.h"
#include "classlist.h"
@@ -201,6 +202,8 @@ class ClassDefImpl
bool isAnonymous;
uint64 spec;
+
+ QCString metaData;
};
void ClassDefImpl::init(const char *defFileName, const char *name,
@@ -671,6 +674,10 @@ void ClassDef::internalInsertMember(MemberDef *md,
case MemberType_Variable:
addMemberToList(MemberListType_variableMembers,md,FALSE);
break;
+ case MemberType_Define:
+ warn(md->getDefFileName(),md->getDefLine()-1,"A define (%s) cannot be made a member of %s",
+ md->name().data(), this->name().data());
+ break;
default:
err("Unexpected member type %d found!\n",md->memberType());
}
@@ -1368,10 +1375,165 @@ QCString ClassDef::includeStatement() const
}
}
+void ClassDef::writeIncludeFilesForSlice(OutputList &ol)
+{
+ if (m_impl->incInfo)
+ {
+ QCString nm;
+ QStrList paths = Config_getList(STRIP_FROM_PATH);
+ if (!paths.isEmpty() && m_impl->incInfo->fileDef)
+ {
+ QCString abs = m_impl->incInfo->fileDef->absFilePath();
+ const char *s = paths.first();
+ QCString potential;
+ unsigned int length = 0;
+ while (s)
+ {
+ QFileInfo info(s);
+ if (info.exists())
+ {
+ QString prefix = info.absFilePath();
+ if (prefix.at(prefix.length() - 1) != '/')
+ {
+ prefix += '/';
+ }
+
+ if (prefix.length() > length &&
+ qstricmp(abs.left(prefix.length()).data(), prefix.data()) == 0) // case insensitive compare
+ {
+ length = prefix.length();
+ potential = abs.right(abs.length() - prefix.length());
+ }
+ s = paths.next();
+ }
+ }
+
+ if (length > 0)
+ {
+ nm = potential;
+ }
+ }
+
+ if (nm.isEmpty())
+ {
+ nm = m_impl->incInfo->includeName.data();
+ }
+
+ ol.startParagraph();
+ ol.docify(theTranslator->trDefinedIn()+" ");
+ ol.startTypewriter();
+ ol.docify("<");
+ if (m_impl->incInfo->fileDef)
+ {
+ ol.writeObjectLink(0,m_impl->incInfo->fileDef->includeName(),0,nm);
+ }
+ else
+ {
+ ol.docify(nm);
+ }
+ ol.docify(">");
+ ol.endTypewriter();
+ ol.endParagraph();
+ }
+
+ // Write a summary of the Slice definition including metadata.
+ ol.startParagraph();
+ ol.startTypewriter();
+ if (!m_impl->metaData.isEmpty())
+ {
+ ol.docify(m_impl->metaData);
+ ol.lineBreak();
+ }
+ if (m_impl->spec & Entry::Local)
+ {
+ ol.docify("local ");
+ }
+ if (m_impl->spec & Entry::Interface)
+ {
+ ol.docify("interface ");
+ }
+ else if (m_impl->spec & Entry::Struct)
+ {
+ ol.docify("struct ");
+ }
+ else if (m_impl->spec & Entry::Exception)
+ {
+ ol.docify("exception ");
+ }
+ else
+ {
+ ol.docify("class ");
+ }
+ ol.docify(stripScope(name()));
+ if (m_impl->inherits)
+ {
+ if (m_impl->spec & (Entry::Interface|Entry::Exception))
+ {
+ ol.docify(" extends ");
+ BaseClassListIterator it(*m_impl->inherits);
+ BaseClassDef *ibcd;
+ for (;(ibcd=it.current());++it)
+ {
+ ClassDef *icd = ibcd->classDef;
+ ol.docify(icd->name());
+ if (!it.atLast())
+ {
+ ol.docify(", ");
+ }
+ }
+ }
+ else
+ {
+ // Must be a class.
+ bool implements = false;
+ BaseClassListIterator it(*m_impl->inherits);
+ BaseClassDef *ibcd;
+ for (;(ibcd=it.current());++it)
+ {
+ ClassDef *icd = ibcd->classDef;
+ if (icd->m_impl->spec & Entry::Interface)
+ {
+ implements = true;
+ }
+ else
+ {
+ ol.docify(" extends ");
+ ol.docify(icd->name());
+ }
+ }
+ if (implements)
+ {
+ ol.docify(" implements ");
+ bool first = true;
+ for (ibcd=it.toFirst();(ibcd=it.current());++it)
+ {
+ ClassDef *icd = ibcd->classDef;
+ if (icd->m_impl->spec & Entry::Interface)
+ {
+ if (!first)
+ {
+ ol.docify(", ");
+ }
+ else
+ {
+ first = false;
+ }
+ ol.docify(icd->name());
+ }
+ }
+ }
+ }
+ }
+ ol.docify(" { ... }");
+ ol.endTypewriter();
+ ol.endParagraph();
+}
+
void ClassDef::writeIncludeFiles(OutputList &ol)
{
if (m_impl->incInfo /*&& Config_getBool(SHOW_INCLUDE_FILES)*/)
{
+ SrcLangExt lang = getLanguage();
QCString nm=m_impl->incInfo->includeName.isEmpty() ?
(m_impl->incInfo->fileDef ?
m_impl->incInfo->fileDef->docName().data() : ""
@@ -1382,7 +1544,6 @@ void ClassDef::writeIncludeFiles(OutputList &ol)
ol.startParagraph();
ol.startTypewriter();
ol.docify(includeStatement());
- SrcLangExt lang = getLanguage();
bool isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java;
if (m_impl->incInfo->local || isIDLorJava)
ol.docify("\"");
@@ -1883,12 +2044,35 @@ void ClassDef::writeDeclarationLink(OutputList &ol,bool &found,const char *heade
{
//static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
//static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
SrcLangExt lang = getLanguage();
if (visibleInParentsDeclList())
{
if (!found) // first class
{
- ol.startMemberHeader("nested-classes");
+ if (sliceOpt)
+ {
+ if (compoundType()==Interface)
+ {
+ ol.startMemberHeader("interfaces");
+ }
+ else if (compoundType()==Struct)
+ {
+ ol.startMemberHeader("structs");
+ }
+ else if (compoundType()==Exception)
+ {
+ ol.startMemberHeader("exceptions");
+ }
+ else // compoundType==Class
+ {
+ ol.startMemberHeader("nested-classes");
+ }
+ }
+ else // non-Slice optimization: single header for class/struct/..
+ {
+ ol.startMemberHeader("nested-classes");
+ }
if (header)
{
ol.parseText(header);
@@ -1914,6 +2098,10 @@ void ClassDef::writeDeclarationLink(OutputList &ol,bool &found,const char *heade
if (lang!=SrcLangExt_VHDL) // for VHDL we swap the name and the type
{
+ if (isSliceLocal())
+ {
+ ol.writeString("local ");
+ }
ol.writeString(ctype);
ol.writeString(" ");
ol.insertMemberAlign();
@@ -2017,7 +2205,14 @@ void ClassDef::writeDocumentationContents(OutputList &ol,const QCString & /*page
writeBriefDescription(ol,exampleFlag);
break;
case LayoutDocEntry::ClassIncludes:
- writeIncludeFiles(ol);
+ if (lang==SrcLangExt_Slice)
+ {
+ writeIncludeFilesForSlice(ol);
+ }
+ else
+ {
+ writeIncludeFiles(ol);
+ }
break;
case LayoutDocEntry::ClassInheritanceGraph:
writeInheritanceGraph(ol);
@@ -2079,8 +2274,14 @@ void ClassDef::writeDocumentationContents(OutputList &ol,const QCString & /*page
case LayoutDocEntry::NamespaceNestedNamespaces:
case LayoutDocEntry::NamespaceNestedConstantGroups:
case LayoutDocEntry::NamespaceClasses:
+ case LayoutDocEntry::NamespaceInterfaces:
+ case LayoutDocEntry::NamespaceStructs:
+ case LayoutDocEntry::NamespaceExceptions:
case LayoutDocEntry::NamespaceInlineClasses:
case LayoutDocEntry::FileClasses:
+ case LayoutDocEntry::FileInterfaces:
+ case LayoutDocEntry::FileStructs:
+ case LayoutDocEntry::FileExceptions:
case LayoutDocEntry::FileNamespaces:
case LayoutDocEntry::FileConstantGroups:
case LayoutDocEntry::FileIncludes:
@@ -2119,6 +2320,12 @@ QCString ClassDef::title() const
m_impl->compType,
m_impl->tempArgs != 0);
}
+ else if (lang==SrcLangExt_Slice)
+ {
+ pageTitle = theTranslator->trCompoundReferenceSlice(displayName(),
+ m_impl->compType,
+ isSliceLocal());
+ }
else if (lang==SrcLangExt_VHDL)
{
pageTitle = theTranslator->trCustomReference(VhdlDocGen::getClassTitle(this));
@@ -2157,9 +2364,35 @@ void ClassDef::writeDocumentation(OutputList &ol)
static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
//static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
//static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
QCString pageTitle = title();
- startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_ClassVisible,!generateTreeView);
+ HighlightedItem hli;
+ if (sliceOpt)
+ {
+ if (compoundType()==Interface)
+ {
+ hli = HLI_InterfaceVisible;
+ }
+ else if (compoundType()==Struct)
+ {
+ hli = HLI_StructVisible;
+ }
+ else if (compoundType()==Exception)
+ {
+ hli = HLI_ExceptionVisible;
+ }
+ else
+ {
+ hli = HLI_ClassVisible;
+ }
+ }
+ else
+ {
+ hli = HLI_ClassVisible;
+ }
+
+ startFile(ol,getOutputFileBase(),name(),pageTitle,hli,!generateTreeView);
if (!generateTreeView)
{
if (getOuterScope()!=Doxygen::globalScope)
@@ -2286,15 +2519,40 @@ void ClassDef::writeMemberList(OutputList &ol)
{
static bool cOpt = Config_getBool(OPTIMIZE_OUTPUT_FOR_C);
//static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
if (m_impl->allMemberNameInfoSDict==0 || cOpt) return;
// only for HTML
ol.pushGeneratorState();
ol.disableAllBut(OutputGenerator::Html);
+ HighlightedItem hli;
+ if (sliceOpt)
+ {
+ if (compoundType()==Interface)
+ {
+ hli = HLI_InterfaceVisible;
+ }
+ else if (compoundType()==Struct)
+ {
+ hli = HLI_StructVisible;
+ }
+ else if (compoundType()==Exception)
+ {
+ hli = HLI_ExceptionVisible;
+ }
+ else
+ {
+ hli = HLI_ClassVisible;
+ }
+ }
+ else
+ {
+ hli = HLI_ClassVisible;
+ }
+
QCString memListFile = getMemberListFileName();
- startFile(ol,memListFile,memListFile,theTranslator->trMemberList(),
- HLI_ClassVisible,!generateTreeView,getOutputFileBase());
+ startFile(ol,memListFile,memListFile,theTranslator->trMemberList(),hli,!generateTreeView,getOutputFileBase());
if (!generateTreeView)
{
if (getOuterScope()!=Doxygen::globalScope)
@@ -4746,12 +5004,22 @@ bool ClassDef::subGrouping() const
return m_impl->subGrouping;
}
+bool ClassDef::isSliceLocal() const
+{
+ return m_impl->spec&Entry::Local;
+}
+
void ClassDef::setName(const char *name)
{
m_impl->isAnonymous = QCString(name).find('@')!=-1;
Definition::setName(name);
}
+void ClassDef::setMetaData(const char *md)
+{
+ m_impl->metaData = md;
+}
+
bool ClassDef::isAnonymous() const
{
return m_impl->isAnonymous;
diff --git a/src/classdef.h b/src/classdef.h
index 12fcd93..14f9fc8 100644
--- a/src/classdef.h
+++ b/src/classdef.h
@@ -336,6 +336,7 @@ class ClassDef : public Definition
QCString getMemberListFileName() const;
bool subGrouping() const;
+ bool isSliceLocal() const;
//-----------------------------------------------------------------------------------
// --- setters ----
@@ -376,6 +377,8 @@ class ClassDef : public Definition
void setTagLessReference(ClassDef *cd);
void setName(const char *name);
+ void setMetaData(const char *md);
+
//-----------------------------------------------------------------------------------
// --- actions ----
//-----------------------------------------------------------------------------------
@@ -429,6 +432,7 @@ class ClassDef : public Definition
void writeDetailedDescription(OutputList &ol,const QCString &pageType,bool exampleFlag,
const QCString &title,const QCString &anchor=QCString());
void writeIncludeFiles(OutputList &ol);
+ void writeIncludeFilesForSlice(OutputList &ol);
//void writeAllMembersLink(OutputList &ol);
void writeInheritanceGraph(OutputList &ol);
void writeCollaborationGraph(OutputList &ol);
diff --git a/src/cmdmapper.cpp b/src/cmdmapper.cpp
index 71da3f3..acbbe44 100644
--- a/src/cmdmapper.cpp
+++ b/src/cmdmapper.cpp
@@ -120,6 +120,7 @@ CommandMap cmdMap[] =
{ ".", CMD_PUNT },
{ "+", CMD_PLUS },
{ "-", CMD_MINUS },
+ { ":", CMD_COLON },
{ "::", CMD_DCOLON },
{ "\"", CMD_QUOTE },
{ "_internalref", CMD_INTERNALREF },
diff --git a/src/cmdmapper.h b/src/cmdmapper.h
index d06de63..c1747ee 100644
--- a/src/cmdmapper.h
+++ b/src/cmdmapper.h
@@ -136,7 +136,8 @@ enum CommandType
CMD_MINUS = 106,
CMD_INCLUDEDOC = 107,
CMD_SNIPPETDOC = 108,
- CMD_SNIPWITHLINES= 109
+ CMD_SNIPWITHLINES= 109,
+ CMD_COLON = 110
};
enum HtmlTagType
diff --git a/src/code.l b/src/code.l
index 87dc1fe..558c439 100644
--- a/src/code.l
+++ b/src/code.l
@@ -122,6 +122,7 @@ static bool g_insideJava;
static bool g_insideCS;
static bool g_insidePHP;
static bool g_insideProtocolList;
+static bool g_insideSlice;
static bool g_lexInit = FALSE;
@@ -983,7 +984,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName
}
}
NamespaceDef *nd = getResolvedNamespace(className);
- if (nd)
+ if (nd && nd->isLinkableInProject())
{
g_theCallContext.setScope(nd);
addToSearchIndex(className);
@@ -1834,7 +1835,8 @@ KEYWORD_OBJC ("@public"|"@private"|"@protected"|"@class"|"@implementation"|"@int
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"|{KEYWORD_OBJC})
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"|"char"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string"|"nullptr")
+TYPEKW ("bool"|"byte"|"char"|"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}"'"))
ARITHOP "+"|"-"|"/"|"*"|"%"|"--"|"++"
@@ -2172,8 +2174,12 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
g_code->codify(yytext);
endFontClass();
}
+<ClassName>{ID}("."{ID})* |
<ClassName>{ID}("::"{ID})* {
- g_curClassName=yytext;
+ if(g_insideCS)
+ g_curClassName=substitute(yytext,".","::");
+ else
+ g_curClassName=yytext;
addType();
if (g_curClassName=="alignas")
{
@@ -2237,7 +2243,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
unput(*yytext);
BEGIN( Body );
}
-<ClassVar>("extends"|"implements") { // Java
+<ClassVar>("extends"|"implements") { // Java, Slice
startFontClass("keyword");
codifyLines(yytext);
endFontClass();
@@ -2538,6 +2544,20 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
addType();
g_name+=yytext;
}
+<Body,TemplDecl,ObjCMethod>{TYPEKWSL}/{B}* {
+ if (!g_insideSlice)
+ {
+ REJECT;
+ }
+ else
+ {
+ startFontClass("keywordtype");
+ g_code->codify(yytext);
+ endFontClass();
+ addType();
+ g_name+=yytext;
+ }
+ }
<Body>"generic"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* {
startFontClass("keyword");
g_code->codify(yytext);
@@ -2629,6 +2649,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
addType();
g_name=varname;
}
+<Body>{SCOPETNAME}{B}*"<"[^\n\/\-\.\{\"\>]*">"/{BN}*"(" |
<Body>{SCOPETNAME}/{BN}*"(" { // a() or c::a() or t<A,B>::a() or A\B\foo()
addType();
generateFunctionLink(*g_code,yytext);
@@ -3008,6 +3029,20 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
g_code->codify(yytext);
endFontClass();
}
+<MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKWSL}/([^a-z_A-Z0-9]) {
+ if (!g_insideSlice)
+ {
+ REJECT;
+ }
+ else
+ {
+ addParmType();
+ g_parmName=yytext;
+ startFontClass("keywordtype");
+ g_code->codify(yytext);
+ endFontClass();
+ }
+ }
<MemberCall2,FuncCall>{FLOWKW}/([^a-z_A-Z0-9]) {
addParmType();
g_parmName=yytext;
@@ -3754,11 +3789,12 @@ void parseCCode(CodeOutputInterface &od,const char *className,const QCString &s,
g_sourceFileDef = new FileDef("",(exName?exName:"generated"));
cleanupSourceDef = TRUE;
}
- g_insideObjC = lang==SrcLangExt_ObjC;
- g_insideJava = lang==SrcLangExt_Java;
- g_insideCS = lang==SrcLangExt_CSharp;
- g_insidePHP = lang==SrcLangExt_PHP;
- g_insideCpp = lang==SrcLangExt_Cpp;
+ g_insideObjC = lang==SrcLangExt_ObjC;
+ g_insideJava = lang==SrcLangExt_Java;
+ g_insideCS = lang==SrcLangExt_CSharp;
+ g_insidePHP = lang==SrcLangExt_PHP;
+ g_insideCpp = lang==SrcLangExt_Cpp;
+ g_insideSlice = lang==SrcLangExt_Slice;
if (g_sourceFileDef)
{
setCurrentDoc("l00001");
diff --git a/src/commentscan.h b/src/commentscan.h
index e202f0a..d324969 100644
--- a/src/commentscan.h
+++ b/src/commentscan.h
@@ -40,7 +40,7 @@ class ParserInterface;
* @param[in,out] lineNr The line number at which the comment block was found.
* When the function returns it will be set to the last line parsed.
* @param[in] isBrief TRUE iff this comment block represents a brief description.
- * @param[in] isJavaDocStyle TRUE iff this comment block is in "JavaDoc" style.
+ * @param[in] isJavadocStyle TRUE iff this comment block is in "Javadoc" style.
* This means that it starts as a brief description until the end of
* the sentences is found and then proceeds as a detailed description.
* @param[in] isInbody TRUE iff this comment block is located in the body of
@@ -65,7 +65,7 @@ bool parseCommentBlock(ParserInterface *parser,
const QCString &fileName,
int &lineNr,
bool isBrief,
- bool isJavaDocStyle,
+ bool isJavadocStyle,
bool isInbody,
Protection &prot,
int &position,
diff --git a/src/commentscan.l b/src/commentscan.l
index ac83729..3be770f 100644
--- a/src/commentscan.l
+++ b/src/commentscan.l
@@ -107,6 +107,10 @@ static bool handleCallgraph(const QCString &, const QCStringList &);
static bool handleHideCallgraph(const QCString &, const QCStringList &);
static bool handleCallergraph(const QCString &, const QCStringList &);
static bool handleHideCallergraph(const QCString &, const QCStringList &);
+static bool handleReferencedByRelation(const QCString &, const QCStringList &);
+static bool handleHideReferencedByRelation(const QCString &, const QCStringList &);
+static bool handleReferencesRelation(const QCString &, const QCStringList &);
+static bool handleHideReferencesRelation(const QCString &, const QCStringList &);
static bool handleInternal(const QCString &, const QCStringList &);
static bool handleLineBr(const QCString &, const QCStringList &);
static bool handleStatic(const QCString &, const QCStringList &);
@@ -214,6 +218,10 @@ static DocCmdMap docCmdMap[] =
{ "hidecallgraph", &handleHideCallgraph, FALSE },
{ "callergraph", &handleCallergraph, FALSE },
{ "hidecallergraph", &handleHideCallergraph, FALSE },
+ { "showrefby", &handleReferencedByRelation, FALSE },
+ { "hiderefby", &handleHideReferencedByRelation, FALSE },
+ { "showrefs", &handleReferencesRelation, FALSE },
+ { "hiderefs", &handleHideReferencesRelation, FALSE },
{ "internal", &handleInternal, TRUE },
{ "_linebr", &handleLineBr, FALSE },
{ "static", &handleStatic, FALSE },
@@ -688,7 +696,13 @@ static void addSection()
static void addCite()
{
- Doxygen::citeDict->insert(yytext);
+ QCString name=yytext;
+ if (yytext[0] =='"')
+ {
+ name=yytext+1;
+ name=name.left(yyleng-2);
+ }
+ Doxygen::citeDict->insert(name.data());
}
//-----------------------------------------------------------------------------
@@ -935,9 +949,9 @@ FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+@&#]
FILE ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]*"\"")
ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
LABELID [a-z_A-Z\x80-\xFF][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 [a-z_A-Z0-9\x80-\xFF\-\?]
+CITEECHAR [a-z_A-Z0-9\x80-\xFF\-\+:\/\?]*
+CITEID {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*|"\""{CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*"\""
SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
SCOPENAME "$"?(({ID}?{BN}*("::"|"."){BN}*)*)((~{BN}*)?{ID})
TMPLSPEC "<"{BN}*[^>]+{BN}*">"
@@ -1589,8 +1603,12 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
<PageDocArg1>. { // ignore other stuff
}
<PageDocArg2>.*"\n" { // second argument; page title
- yyLineNr++;
- current->args = yytext;
+ yyLineNr++;
+ // bug 748927
+ QCString tmp = yytext;
+ tmp = substitute(substitute(tmp,"@<","&lt;"),"@>","&gt;");
+ tmp = substitute(substitute(tmp,"\\<","&lt;"),"\\>","&gt;");
+ current->args = tmp;
addOutput('\n');
BEGIN( Comment );
}
@@ -2831,6 +2849,30 @@ static bool handleHideCallergraph(const QCString &, const QCStringList &)
return FALSE;
}
+static bool handleReferencedByRelation(const QCString &, const QCStringList &)
+{
+ current->referencedByRelation = TRUE; // ON
+ return FALSE;
+}
+
+static bool handleHideReferencedByRelation(const QCString &, const QCStringList &)
+{
+ current->referencedByRelation = FALSE; // OFF
+ return FALSE;
+}
+
+static bool handleReferencesRelation(const QCString &, const QCStringList &)
+{
+ current->referencesRelation = TRUE; // ON
+ return FALSE;
+}
+
+static bool handleHideReferencesRelation(const QCString &, const QCStringList &)
+{
+ current->referencesRelation = FALSE; // OFF
+ return FALSE;
+}
+
static bool handleInternal(const QCString &, const QCStringList &)
{
if (!Config_getBool(INTERNAL_DOCS))
diff --git a/src/config.h b/src/config.h
index 98f5a92..102774e 100644
--- a/src/config.h
+++ b/src/config.h
@@ -66,7 +66,7 @@ namespace Config
* and replaces environment variables.
* \param clearHeaderAndFooter set to TRUE when writing header and footer templates.
*/
- void postProcess(bool clearHeaderAndFooter);
+ void postProcess(bool clearHeaderAndFooter, bool compare = FALSE);
/*! Check the validity of the parsed options and correct or warn the user where needed. */
void checkAndCorrect();
diff --git a/src/config.xml b/src/config.xml
index 08795dc..db0f557 100644
--- a/src/config.xml
+++ b/src/config.xml
@@ -4,13 +4,13 @@
<![CDATA[
/*
*
- *
+ *
*
* 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.
*
@@ -41,28 +41,28 @@ Each statement consists of a \c TAG_NAME written in capitals,
followed by the equal sign (<code>=</code>) and one or more values. If the same tag
is assigned more than once, the last assignment overwrites any earlier
assignment. For tags that take a list as their argument,
-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
+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
+as the last character of a line. Environment variables can be expanded
using the pattern <code>\$(ENV_VARIABLE_NAME)</code>.
You can also include part of a configuration file from another configuration
file using a <code>\@INCLUDE</code> tag as follows:
\verbatim
@INCLUDE = config_file_name
-\endverbatim
-The include file is searched in the current working directory. You can
+\endverbatim
+The include file is searched in the current working directory. You can
also specify a list of directories that should be searched before looking
-in the current working directory. Do this by putting a <code>\@INCLUDE_PATH</code> tag
+in the current working directory. Do this by putting a <code>\@INCLUDE_PATH</code> tag
with these paths before the <code>\@INCLUDE</code> tag, e.g.:
\verbatim
@INCLUDE_PATH = my_config_dir
\endverbatim
The configuration options can be divided into several categories.
-Below is an alphabetical index of the tags that are recognized
+Below is an alphabetical index of the tags that are recognized
followed by the descriptions of the tags grouped by category.
]]>
</docs>
@@ -91,14 +91,14 @@ Values that contain spaces should be placed between quotes (\" \").
<![CDATA[
\section config_examples Examples
-Suppose you have a simple project consisting of two files: a source file
+Suppose you have a simple project consisting of two files: a source file
\c example.cc and a header file \c example.h.
Then a minimal configuration file is as simple as:
\verbatim
INPUT = example.cc example.h
\endverbatim
-Assuming the example makes use of Qt classes and \c perl is located
+Assuming the example makes use of Qt classes and \c perl is located
in <code>/usr/bin</code>, a more realistic configuration file would be:
\verbatim
PROJECT_NAME = Example
@@ -109,7 +109,7 @@ PERL_PATH = /usr/local/bin/perl
SEARCHENGINE = NO
\endverbatim
-To generate the documentation for the
+To generate the documentation for the
<a href="https://sourceforge.net/projects/qdbttabular/">QdbtTabular</a> package
I have used the following configuration file:
\verbatim
@@ -160,7 +160,7 @@ INPUT = $(QTDIR)/doc \
$(QTDIR)/src/dialogs \
$(QTDIR)/src/tools
FILE_PATTERNS = *.cpp *.h q*.doc
-INCLUDE_PATH = $(QTDIR)/include
+INCLUDE_PATH = $(QTDIR)/include
RECURSIVE = YES
\endverbatim
@@ -212,7 +212,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='string' id='DOXYFILE_ENCODING' format='string' defval='UTF-8'>
<docs>
<![CDATA[
- This tag specifies the encoding used for all characters in the configuration file that
+ This tag specifies the encoding used for all characters in the configuration file that
follow. The default is UTF-8 which is also the encoding used for all text before
the first occurrence of this tag. Doxygen uses \c libiconv (or the iconv built into
\c libc) for the transcoding. See https://www.gnu.org/software/libiconv/ for the list of
@@ -224,8 +224,8 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
The \c PROJECT_NAME tag is a single word (or a sequence of words
- surrounded by double-quotes, unless you are using Doxywizard) that should identify the project for which the
- documentation is generated. This name is used in the title of most
+ surrounded by double-quotes, unless you are using Doxywizard) that should identify the project for which the
+ documentation is generated. This name is used in the title of most
generated pages and in a few other places.
]]>
</docs>
@@ -242,9 +242,9 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='string' id='PROJECT_BRIEF' format='string' defval=''>
<docs>
<![CDATA[
- Using the \c PROJECT_BRIEF tag one can provide an optional one line description
- for a project that appears at the top of each page and should give viewer
- a quick idea about the purpose of the project. Keep the description short.
+ Using the \c PROJECT_BRIEF tag one can provide an optional one line description
+ for a project that appears at the top of each page and should give viewer
+ a quick idea about the purpose of the project. Keep the description short.
]]>
</docs>
</option>
@@ -252,9 +252,9 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='string' id='PROJECT_LOGO' format='image' defval=''>
<docs>
<![CDATA[
- With the \c PROJECT_LOGO tag one can specify a logo or an icon that is
- included in the documentation. The maximum height of the logo should not
- exceed 55 pixels and the maximum width should not exceed 200 pixels.
+ With the \c PROJECT_LOGO tag one can specify a logo or an icon that is
+ included in the documentation. The maximum height of the logo should not
+ exceed 55 pixels and the maximum width should not exceed 200 pixels.
Doxygen will copy the logo to the output directory.
]]>
</docs>
@@ -262,9 +262,9 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='string' id='OUTPUT_DIRECTORY' format='dir' defval=''>
<docs>
<![CDATA[
- The \c OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
- path into which the generated documentation will be written.
- If a relative path is entered, it will be relative to the location
+ The \c OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+ path into which the generated documentation will be written.
+ If a relative path is entered, it will be relative to the location
where doxygen was started. If left blank the current directory will be used.
]]>
</docs>
@@ -273,11 +273,11 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
If the \c CREATE_SUBDIRS tag is set to \c YES then doxygen will create
- 4096 sub-directories (in 2 levels) under the output directory of each output
- format and will distribute the generated files over these directories.
+ 4096 sub-directories (in 2 levels) under the output directory of each output
+ format and will distribute the generated files over these directories.
Enabling this option can be useful when feeding doxygen a huge amount of source
files, where putting all generated files in the same directory would otherwise
- causes performance problems for the file system.
+ causes performance problems for the file system.
]]>
</docs>
</option>
@@ -285,8 +285,8 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
If the \c ALLOW_UNICODE_NAMES tag is set to \c YES,
- doxygen will allow non-ASCII characters to appear in the names of generated files.
- If set to \c NO, non-ASCII characters will be escaped, for example _xE3_x81_x84
+ doxygen will allow non-ASCII characters to appear in the names of generated files.
+ If set to \c NO, non-ASCII characters will be escaped, for example _xE3_x81_x84
will be used for Unicode U+3044.
]]>
</docs>
@@ -369,12 +369,12 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='REPEAT_BRIEF' defval='1'>
<docs>
<![CDATA[
- If the \c REPEAT_BRIEF tag is set to \c YES, doxygen will
- prepend the brief description of a member or function before the detailed
- description
- <br>Note:
+ If the \c REPEAT_BRIEF tag is set to \c YES, doxygen will
+ prepend the brief description of a member or function before the detailed
+ description
+ <br>Note:
If both \ref cfg_hide_undoc_members "HIDE_UNDOC_MEMBERS" and
- \ref cfg_brief_member_desc "BRIEF_MEMBER_DESC" are set to \c NO, the
+ \ref cfg_brief_member_desc "BRIEF_MEMBER_DESC" are set to \c NO, the
brief descriptions will be completely suppressed.
]]>
</docs>
@@ -388,7 +388,7 @@ Go to the <a href="commands.html">next</a> section or return to the
stripped from the text and the result, after processing the whole list, is used
as the annotated text. Otherwise, the brief description is used as-is. If left
blank, the following values are used (`$name` is automatically replaced with the
- name of the entity):
+ name of the entity):
]]>
</docs>
<value name='The $name class'/>
@@ -406,7 +406,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='ALWAYS_DETAILED_SEC' defval='0'>
<docs>
<![CDATA[
- If the \c ALWAYS_DETAILED_SEC and \ref cfg_repeat_brief "REPEAT_BRIEF" tags
+ If the \c ALWAYS_DETAILED_SEC and \ref cfg_repeat_brief "REPEAT_BRIEF" tags
are both set to \c YES then
doxygen will generate a detailed section even if there is only a brief
description.
@@ -437,12 +437,12 @@ Go to the <a href="commands.html">next</a> section or return to the
<![CDATA[
The \c STRIP_FROM_PATH tag
can be used to strip a user-defined part of the path. Stripping is
- only done if one of the specified strings matches the left-hand part of the
+ only done if one of the specified strings matches the left-hand part of the
path. The tag can be used to show relative paths in the file list.
If left blank the directory from which doxygen is run is used as the
path to strip.
- <br>Note that you can specify absolute paths here, but also
- relative paths, which will be relative from the directory where doxygen is
+ <br>Note that you can specify absolute paths here, but also
+ relative paths, which will be relative from the directory where doxygen is
started.
]]>
</docs>
@@ -451,11 +451,11 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='list' id='STRIP_FROM_INC_PATH' format='string'>
<docs>
<![CDATA[
- The \c STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+ The \c STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
the path mentioned in the documentation of a class, which tells
- the reader which header file to include in order to use a class.
+ the reader which header file to include in order to use a class.
If left blank only the name of the header file containing the class
- definition is used. Otherwise one should specify the list of include paths that
+ definition is used. Otherwise one should specify the list of include paths that
are normally passed to the compiler using the `-I` flag.
]]>
</docs>
@@ -474,7 +474,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<![CDATA[
If the \c JAVADOC_AUTOBRIEF tag is set to \c YES then doxygen
will interpret the first line (until the first dot) of a Javadoc-style
- comment as the brief description. If set to \c NO, the
+ comment as the brief description. If set to \c NO, the
Javadoc-style will behave just like regular Qt-style comments
(thus requiring an explicit \ref cmdbrief "\@brief" command for a brief description.)
]]>
@@ -534,20 +534,20 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
This tag can be used to specify a number of aliases that act
- as commands in the documentation. An alias has the form:
+ as commands in the documentation. An alias has the form:
\verbatim
name=value
\endverbatim
- For example adding
+ For example adding
\verbatim
- "sideeffect=@par Side Effects:\n"
+ "sideeffect=@par Side Effects:\n"
\endverbatim
will allow you to
- put the command \c \\sideeffect (or \c \@sideeffect) in the documentation, which
+ put the command \c \\sideeffect (or \c \@sideeffect) in the documentation, which
will result in a user-defined paragraph with heading "Side Effects:".
You can put \ref cmdn "\\n"'s in the value part of an alias to insert newlines
(in the resulting output).
- You can put `^^` in the value part of an alias to insert a newline as if
+ You can put `^^` in the value part of an alias to insert a newline as if
a physical newline was in the original file.
]]>
</docs>
@@ -579,9 +579,9 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='list' id='TCL_SUBST' format='string'>
<docs>
<![CDATA[
- This tag can be used to specify a number of word-keyword mappings (TCL only).
- A mapping has the form <code>"name=value"</code>. For example adding
- <code>"class=itcl::class"</code> will allow you to use the command class in the
+ This tag can be used to specify a number of word-keyword mappings (TCL only).
+ A mapping has the form <code>"name=value"</code>. For example adding
+ <code>"class=itcl::class"</code> will allow you to use the command class in the
<code>itcl::class</code> meaning.
]]>
</docs>
@@ -589,10 +589,10 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='OPTIMIZE_OUTPUT_FOR_C' defval='0'>
<docs>
<![CDATA[
- Set the \c OPTIMIZE_OUTPUT_FOR_C tag to \c YES if your project consists
- of C sources only. Doxygen will then generate output that is more tailored
- for C. For instance, some of the names that are used will be different.
- The list of all members will be omitted, etc.
+ Set the \c OPTIMIZE_OUTPUT_FOR_C tag to \c YES if your project consists
+ of C sources only. Doxygen will then generate output that is more tailored
+ for C. For instance, some of the names that are used will be different.
+ The list of all members will be omitted, etc.
]]>
</docs>
</option>
@@ -600,16 +600,16 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
Set the \c OPTIMIZE_OUTPUT_JAVA tag to \c YES if your project consists of Java or
- Python sources only. Doxygen will then generate output that is more tailored
- for that language. For instance, namespaces will be presented as packages,
- qualified scopes will look different, etc.
+ Python sources only. Doxygen will then generate output that is more tailored
+ for that language. For instance, namespaces will be presented as packages,
+ qualified scopes will look different, etc.
]]>
</docs>
</option>
<option type='bool' id='OPTIMIZE_FOR_FORTRAN' defval='0'>
<docs>
<![CDATA[
- Set the \c OPTIMIZE_FOR_FORTRAN tag to \c YES if your project consists of Fortran
+ Set the \c OPTIMIZE_FOR_FORTRAN tag to \c YES if your project consists of Fortran
sources. Doxygen will then generate output that is tailored for Fortran.
]]>
</docs>
@@ -617,11 +617,21 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='OPTIMIZE_OUTPUT_VHDL' defval='0'>
<docs>
<![CDATA[
- Set the \c OPTIMIZE_OUTPUT_VHDL tag to \c YES if your project consists of VHDL
+ Set the \c OPTIMIZE_OUTPUT_VHDL tag to \c YES if your project consists of VHDL
sources. Doxygen will then generate output that is tailored for VHDL.
]]>
</docs>
</option>
+ <option type='bool' id='OPTIMIZE_OUTPUT_SLICE' defval='0'>
+ <docs>
+<![CDATA[
+ Set the \c OPTIMIZE_OUTPUT_SLICE tag to \c YES if your project consists of Slice
+ sources only. Doxygen will then generate output that is more tailored
+ for that language. For instance, namespaces will be presented as modules,
+ types will be separated into more groups, etc.
+]]>
+ </docs>
+ </option>
<option type='list' id='EXTENSION_MAPPING' format='string'>
<docs>
<![CDATA[
@@ -630,7 +640,7 @@ Go to the <a href="commands.html">next</a> section or return to the
Doxygen has a built-in mapping, but you can override or extend it using this tag.
The format is <code>ext=language</code>, where \c ext is a file extension, and language is one of
the parsers supported by doxygen: IDL, Java, Javascript, Csharp (C#), C, C++, D, PHP,
- md (Markdown), Objective-C, Python, Fortran (fixed format Fortran: FortranFixed,
+ md (Markdown), Objective-C, Python, Slice, Fortran (fixed format Fortran: FortranFixed,
free formatted Fortran: FortranFree, unknown formatted Fortran: Fortran. In
the later case the parser tries to guess whether the code is fixed or free
formatted code, this is the default for Fortran type files), VHDL, tcl.
@@ -640,7 +650,7 @@ Go to the <a href="commands.html">next</a> section or return to the
use: `inc=Fortran f=C`.
<br>Note: For files without extension you can use `no_extension` as a placeholder.
- <br>Note that for custom extensions you also need to set \ref cfg_file_patterns "FILE_PATTERNS" otherwise the
+ <br>Note that for custom extensions you also need to set \ref cfg_file_patterns "FILE_PATTERNS" otherwise the
files are not read by doxygen.
]]>
</docs>
@@ -648,12 +658,12 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='MARKDOWN_SUPPORT' defval='1'>
<docs>
<![CDATA[
- If the \c MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all
- comments according to the Markdown format, which allows for more readable
- documentation. See http://daringfireball.net/projects/markdown/ for details.
- The output of markdown processing is further processed by doxygen, so you
- can mix doxygen, HTML, and XML commands with Markdown formatting.
- Disable only in case of backward compatibilities issues.
+ If the \c MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all
+ comments according to the Markdown format, which allows for more readable
+ documentation. See https://daringfireball.net/projects/markdown/ for details.
+ The output of markdown processing is further processed by doxygen, so you
+ can mix doxygen, HTML, and XML commands with Markdown formatting.
+ Disable only in case of backward compatibilities issues.
]]>
</docs>
</option>
@@ -670,9 +680,9 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='AUTOLINK_SUPPORT' defval='1'>
<docs>
<![CDATA[
- When enabled doxygen tries to link words that correspond to documented classes,
- or namespaces to their corresponding documentation. Such a link can be
- prevented in individual cases by putting a \c % sign in front of the word or
+ When enabled doxygen tries to link words that correspond to documented classes,
+ or namespaces to their corresponding documentation. Such a link can be
+ prevented in individual cases by putting a \c % sign in front of the word or
globally by setting \c AUTOLINK_SUPPORT to \c NO.
]]>
</docs>
@@ -700,10 +710,10 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='SIP_SUPPORT' defval='0'>
<docs>
<![CDATA[
- Set the \c SIP_SUPPORT tag to \c YES if your project consists
- of <a href="https://www.riverbankcomputing.com/software/sip/intro">sip</a> sources only.
- Doxygen will parse them like normal C++ but will assume all classes use public
- instead of private inheritance when no explicit protection keyword is present.
+ Set the \c SIP_SUPPORT tag to \c YES if your project consists
+ of <a href="https://www.riverbankcomputing.com/software/sip/intro">sip</a> sources only.
+ Doxygen will parse them like normal C++ but will assume all classes use public
+ instead of private inheritance when no explicit protection keyword is present.
]]>
</docs>
</option>
@@ -713,8 +723,8 @@ Go to the <a href="commands.html">next</a> section or return to the
For Microsoft's IDL there are \c propget and \c propput attributes to indicate getter
and setter methods for a property. Setting this option to \c YES
will make doxygen to replace the get and set methods by a property in the
- documentation. This will only work if the methods are indeed getting or
- setting a simple type. If this is not the case, or you want to show the
+ documentation. This will only work if the methods are indeed getting or
+ setting a simple type. If this is not the case, or you want to show the
methods anyway, you should set this option to \c NO.
]]>
</docs>
@@ -745,16 +755,16 @@ Go to the <a href="commands.html">next</a> section or return to the
the same type (for instance a group of public functions) to be put as a
subgroup of that type (e.g. under the Public Functions section). Set it to
\c NO to prevent subgrouping. Alternatively, this can be done per class using
- the \ref cmdnosubgrouping "\\nosubgrouping" command.
+ the \ref cmdnosubgrouping "\\nosubgrouping" command.
]]>
</docs>
</option>
<option type='bool' id='INLINE_GROUPED_CLASSES' defval='0'>
<docs>
<![CDATA[
- When the \c INLINE_GROUPED_CLASSES tag is set to \c YES, classes, structs and
- unions are shown inside the group in which they are included
- (e.g. using \ref cmdingroup "\\ingroup") instead of on a separate page (for HTML and Man pages)
+ When the \c INLINE_GROUPED_CLASSES tag is set to \c YES, classes, structs and
+ unions are shown inside the group in which they are included
+ (e.g. using \ref cmdingroup "\\ingroup") instead of on a separate page (for HTML and Man pages)
or section (for \f$\mbox{\LaTeX}\f$ and RTF).
<br>Note that this feature does not work in
combination with \ref cfg_separate_member_pages "SEPARATE_MEMBER_PAGES".
@@ -764,11 +774,11 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='INLINE_SIMPLE_STRUCTS' defval='0'>
<docs>
<![CDATA[
- When the \c INLINE_SIMPLE_STRUCTS tag is set to \c YES, structs, classes, and
- unions with only public data fields or simple typedef fields will be shown
- inline in the documentation of the scope in which they are defined (i.e. file,
- namespace, or group documentation), provided this scope is documented. If set
- to \c NO, structs, classes, and unions are shown on a separate
+ When the \c INLINE_SIMPLE_STRUCTS tag is set to \c YES, structs, classes, and
+ unions with only public data fields or simple typedef fields will be shown
+ inline in the documentation of the scope in which they are defined (i.e. file,
+ namespace, or group documentation), provided this scope is documented. If set
+ to \c NO, structs, classes, and unions are shown on a separate
page (for HTML and Man pages) or section (for \f$\mbox{\LaTeX}\f$ and RTF).
]]>
</docs>
@@ -777,11 +787,11 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
When \c TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or enum
- is documented as struct, union, or enum with the name of the typedef. So
- <code>typedef struct TypeS {} TypeT</code>, will appear in the documentation as a struct
- with name \c TypeT. When disabled the typedef will appear as a member of a file,
- namespace, or class. And the struct will be named \c TypeS. This can typically
- be useful for C code in case the coding convention dictates that all compound
+ is documented as struct, union, or enum with the name of the typedef. So
+ <code>typedef struct TypeS {} TypeT</code>, will appear in the documentation as a struct
+ with name \c TypeT. When disabled the typedef will appear as a member of a file,
+ namespace, or class. And the struct will be named \c TypeS. This can typically
+ be useful for C code in case the coding convention dictates that all compound
types are typedef'ed and only the typedef is referenced, never the tag name.
]]>
</docs>
@@ -790,14 +800,14 @@ Go to the <a href="commands.html">next</a> section or return to the
<!-- be careful when changing these formulas as they are hard coded in the conversion script -->
<docs>
<![CDATA[
- The size of the symbol lookup cache can be
- set using \c LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
- their name and scope. Since this can be an expensive process and often the
- same symbol appears multiple times in the code, doxygen keeps a cache of
- pre-resolved symbols. If the cache is too small doxygen will become slower.
- If the cache is too large, memory is wasted. The cache size is given by this
- formula: \f$2^{(16+\mbox{LOOKUP\_CACHE\_SIZE})}\f$. The valid range is 0..9, the default is 0,
- corresponding to a cache size of \f$2^{16} = 65536\f$ symbols.
+ The size of the symbol lookup cache can be
+ set using \c LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+ their name and scope. Since this can be an expensive process and often the
+ same symbol appears multiple times in the code, doxygen keeps a cache of
+ pre-resolved symbols. If the cache is too small doxygen will become slower.
+ If the cache is too large, memory is wasted. The cache size is given by this
+ formula: \f$2^{(16+\mbox{LOOKUP\_CACHE\_SIZE})}\f$. The valid range is 0..9, the default is 0,
+ corresponding to a cache size of \f$2^{16} = 65536\f$ symbols.
At the end of a run doxygen will report the cache usage and suggest the
optimal cache size from a speed point of view.
]]>
@@ -808,14 +818,14 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='EXTRACT_ALL' defval='0'>
<docs>
<![CDATA[
- If the \c EXTRACT_ALL tag is set to \c YES, doxygen will assume all
- entities in documentation are documented, even if no documentation was
- available. Private class members and static file members will be hidden
- unless the \ref cfg_extract_private "EXTRACT_PRIVATE" respectively
+ If the \c EXTRACT_ALL tag is set to \c YES, doxygen will assume all
+ entities in documentation are documented, even if no documentation was
+ available. Private class members and static file members will be hidden
+ unless the \ref cfg_extract_private "EXTRACT_PRIVATE" respectively
\ref cfg_extract_static "EXTRACT_STATIC" tags are set to \c YES.
- \note This will also disable the warnings about undocumented members
- that are normally produced when \ref cfg_warnings "WARNINGS" is
+ \note This will also disable the warnings about undocumented members
+ that are normally produced when \ref cfg_warnings "WARNINGS" is
set to \c YES.
]]>
</docs>
@@ -823,7 +833,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='EXTRACT_PRIVATE' defval='0'>
<docs>
<![CDATA[
- If the \c EXTRACT_PRIVATE tag is set to \c YES, all private members of a
+ If the \c EXTRACT_PRIVATE tag is set to \c YES, all private members of a
class will be included in the documentation.
]]>
</docs>
@@ -831,8 +841,8 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='EXTRACT_PACKAGE' defval='0'>
<docs>
<![CDATA[
- If the \c EXTRACT_PACKAGE tag is set to \c YES, all members with package
- or internal scope will be included in the documentation.
+ If the \c EXTRACT_PACKAGE tag is set to \c YES, all members with package
+ or internal scope will be included in the documentation.
]]>
</docs>
</option>
@@ -847,8 +857,8 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='EXTRACT_LOCAL_CLASSES' defval='1'>
<docs>
<![CDATA[
- If the \c EXTRACT_LOCAL_CLASSES tag is set to \c YES, classes (and structs)
- defined locally in source files will be included in the documentation.
+ If the \c EXTRACT_LOCAL_CLASSES tag is set to \c YES, classes (and structs)
+ defined locally in source files will be included in the documentation.
If set to \c NO, only classes defined in header files are included. Does not
have any effect for Java sources.
]]>
@@ -857,7 +867,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='EXTRACT_LOCAL_METHODS' defval='0'>
<docs>
<![CDATA[
- This flag is only useful for Objective-C code. If set to \c YES, local
+ This flag is only useful for Objective-C code. If set to \c YES, local
methods, which are defined in the implementation section but not in
the interface are included in the documentation.
If set to \c NO, only methods in the interface are included.
@@ -878,7 +888,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
If the \c HIDE_UNDOC_MEMBERS tag is set to \c YES, doxygen will hide all
- undocumented members inside documented classes or files.
+ undocumented members inside documented classes or files.
If set to \c NO these members will be included in the
various overviews, but no documentation section is generated.
This option has no effect if \ref cfg_extract_all "EXTRACT_ALL" is enabled.
@@ -889,7 +899,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
If the \c HIDE_UNDOC_CLASSES tag is set to \c YES, doxygen will hide all
- undocumented classes that are normally visible in the class hierarchy.
+ undocumented classes that are normally visible in the class hierarchy.
If set to \c NO, these classes will be included in the
various overviews.
This option has no effect if \ref cfg_extract_all "EXTRACT_ALL" is enabled.
@@ -909,9 +919,9 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='HIDE_IN_BODY_DOCS' defval='0'>
<docs>
<![CDATA[
- If the \c HIDE_IN_BODY_DOCS tag is set to \c YES, doxygen will hide any
+ If the \c HIDE_IN_BODY_DOCS tag is set to \c YES, doxygen will hide any
documentation blocks found inside the body of a function.
- If set to \c NO, these blocks will be appended to the
+ If set to \c NO, these blocks will be appended to the
function's detailed documentation block.
]]>
</docs>
@@ -941,9 +951,9 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='HIDE_SCOPE_NAMES' defval='0'>
<docs>
<![CDATA[
- If the \c HIDE_SCOPE_NAMES tag is set to \c NO then doxygen
+ If the \c HIDE_SCOPE_NAMES tag is set to \c NO then doxygen
will show members with their full class and namespace scopes in the
- documentation. If set to \c YES, the scope will be hidden.
+ documentation. If set to \c YES, the scope will be hidden.
]]>
</docs>
</option>
@@ -952,7 +962,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<![CDATA[
If the \c HIDE_COMPOUND_REFERENCE tag is set to \c NO (default) then
doxygen will append additional text to a page's title, such as Class Reference.
- If set to \c YES the compound reference will be hidden.
+ If set to \c YES the compound reference will be hidden.
]]>
</docs>
</option>
@@ -960,7 +970,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
If the \c SHOW_INCLUDE_FILES tag is set to \c YES then doxygen
- will put a list of the files that are included by a file in the documentation
+ will put a list of the files that are included by a file in the documentation
of that file.
]]>
</docs>
@@ -968,7 +978,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='SHOW_GROUPED_MEMB_INC' defval='0'>
<docs>
<![CDATA[
- If the SHOW_GROUPED_MEMB_INC tag is set to \c YES then Doxygen
+ If the SHOW_GROUPED_MEMB_INC tag is set to \c YES then Doxygen
will add for each grouped member an include statement to the documentation,
telling the reader which file to include in order to use the member.
]]>
@@ -977,8 +987,8 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='FORCE_LOCAL_INCLUDES' defval='0'>
<docs>
<![CDATA[
- If the \c FORCE_LOCAL_INCLUDES tag is set to \c YES then doxygen
- will list include files with double quotes in the documentation
+ If the \c FORCE_LOCAL_INCLUDES tag is set to \c YES then doxygen
+ will list include files with double quotes in the documentation
rather than with sharp brackets.
]]>
</docs>
@@ -1030,9 +1040,9 @@ Go to the <a href="commands.html">next</a> section or return to the
<option type='bool' id='SORT_GROUP_NAMES' defval='0'>
<docs>
<![CDATA[
- If the \c SORT_GROUP_NAMES tag is set to \c YES then doxygen will sort the
+ If the \c SORT_GROUP_NAMES tag is set to \c YES then doxygen will sort the
hierarchy of group names into alphabetical order. If set to \c NO
- the group names will appear in their defined order.
+ the group names will appear in their defined order.
]]>
</docs>
</option>
@@ -1044,7 +1054,7 @@ Go to the <a href="commands.html">next</a> section or return to the
\c NO, the class list will be sorted only by class name,
not including the namespace part.
\note This option is not very useful if \ref cfg_hide_scope_names "HIDE_SCOPE_NAMES" is set to \c YES.
- \note This option applies only to the class list, not to the
+ \note This option applies only to the class list, not to the
alphabetical list.
]]>
</docs>
@@ -1053,10 +1063,10 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
If the \c STRICT_PROTO_MATCHING option is enabled and doxygen fails to
- do proper type resolution of all parameters of a function it will reject a
+ do proper type resolution of all parameters of a function it will reject a
match between the prototype and the implementation of a member function even
if there is only one candidate or it is obvious which candidate to choose
- by doing a simple string match. By disabling \c STRICT_PROTO_MATCHING doxygen
+ by doing a simple string match. By disabling \c STRICT_PROTO_MATCHING doxygen
will still accept a match between prototype and implementation in such cases.
]]>
</docs>
@@ -1065,7 +1075,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
The \c GENERATE_TODOLIST tag can be used to enable (\c YES) or
- disable (\c NO) the todo list. This list is created by
+ disable (\c NO) the todo list. This list is created by
putting \ref cmdtodo "\\todo" commands in the documentation.
]]>
</docs>
@@ -1074,7 +1084,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
The \c GENERATE_TESTLIST tag can be used to enable (\c YES) or
- disable (\c NO) the test list. This list is created by
+ disable (\c NO) the test list. This list is created by
putting \ref cmdtest "\\test" commands in the documentation.
]]>
</docs>
@@ -1083,7 +1093,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
The \c GENERATE_BUGLIST tag can be used to enable (\c YES) or
- disable (\c NO) the bug list. This list is created by
+ disable (\c NO) the bug list. This list is created by
putting \ref cmdbug "\\bug" commands in the documentation.
]]>
</docs>
@@ -1092,7 +1102,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
The \c GENERATE_DEPRECATEDLIST tag can be used to enable (\c YES) or
- disable (\c NO) the deprecated list. This list is created by
+ disable (\c NO) the deprecated list. This list is created by
putting \ref cmddeprecated "\\deprecated"
commands in the documentation.
]]>
@@ -1102,7 +1112,7 @@ Go to the <a href="commands.html">next</a> section or return to the
<docs>
<![CDATA[
The \c ENABLED_SECTIONS tag can be used to enable conditional
- documentation sections, marked by \ref cmdif "\\if" \<section_label\> ...
+ documentation sections, marked by \ref cmdif "\\if" \<section_label\> ...
\ref cmdendif "\\endif" and \ref cmdcond "\\cond" \<section_label\> ...
\ref cmdendcond "\\endcond" blocks.
]]>
@@ -1154,9 +1164,9 @@ Go to the <a href="commands.html">next</a> section or return to the
The \c FILE_VERSION_FILTER tag can be used to specify a program or script that
doxygen should invoke to get the current version for each file (typically from the
version control system). Doxygen will invoke the program by executing (via
- <code>popen()</code>) the command <code>command input-file</code>, where \c command is
- the value of the \c FILE_VERSION_FILTER tag, and \c input-file is the name
- of an input file provided by doxygen.
+ <code>popen()</code>) the command <code>command input-file</code>, where \c command is
+ the value of the \c FILE_VERSION_FILTER tag, and \c input-file is the name
+ of an input file provided by doxygen.
Whatever the program writes to standard output is used as the file version.
]]>
</docs>
@@ -1173,8 +1183,8 @@ Example shell script for CVS:
\verbatim
#!/bin/sh
cvs status $1 | sed -n 's/^[ \]*Working revision:[ \t]*\([0-9][0-9\.]*\).*/\1/p'
-\endverbatim
-<br>
+\endverbatim
+<br>
Example shell script for Subversion:
\verbatim
#!/bin/sh
@@ -1202,8 +1212,8 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
doxygen's defaults, run doxygen with the `-l` option. You can optionally specify a
file name after the option, if omitted \c DoxygenLayout.xml will be used as the name
of the layout file.
- <br>Note that if you run doxygen from a directory containing
- a file called \c DoxygenLayout.xml, doxygen will parse it automatically even if
+ <br>Note that if you run doxygen from a directory containing
+ a file called \c DoxygenLayout.xml, doxygen will parse it automatically even if
the \c LAYOUT_FILE tag is left empty.
]]>
</docs>
@@ -1211,11 +1221,11 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<option type='list' id='CITE_BIB_FILES' format='file'>
<docs>
<![CDATA[
- The \c CITE_BIB_FILES tag can be used to specify one or more \c bib files
- containing the reference definitions. This must be a list of <code>.bib</code> files. The
- <code>.bib</code> extension is automatically appended if omitted. This requires the
+ The \c CITE_BIB_FILES tag can be used to specify one or more \c bib files
+ containing the reference definitions. This must be a list of <code>.bib</code> files. The
+ <code>.bib</code> extension is automatically appended if omitted. This requires the
\c bibtex tool to be installed. See also https://en.wikipedia.org/wiki/BibTeX for
- more info. For \f$\mbox{\LaTeX}\f$ the style of the bibliography can be controlled
+ more info. For \f$\mbox{\LaTeX}\f$ the style of the bibliography can be controlled
using \ref cfg_latex_bib_style "LATEX_BIB_STYLE".
To use this feature you need \c bibtex and \c perl available in the search path.
See also \ref cmdcite "\\cite" for info how to create references.
@@ -1236,7 +1246,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<docs>
<![CDATA[
The \c WARNINGS tag can be used to turn on/off the warning messages that are
- generated to standard error (\c stderr) by doxygen. If \c WARNINGS is set to
+ generated to standard error (\c stderr) by doxygen. If \c WARNINGS is set to
\c YES this implies that the warnings are on.
<br>
\b Tip: Turn warnings on while writing the documentation.
@@ -1258,14 +1268,14 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
If the \c WARN_IF_DOC_ERROR tag is set to \c YES, doxygen will generate warnings for
potential errors in the documentation, such as not documenting some
parameters in a documented function, or documenting parameters that
- don't exist or using markup commands wrongly.
+ don't exist or using markup commands wrongly.
]]>
</docs>
</option>
<option type='bool' id='WARN_NO_PARAMDOC' defval='0'>
<docs>
<![CDATA[
- This \c WARN_NO_PARAMDOC option can be enabled to get warnings for
+ This \c WARN_NO_PARAMDOC option can be enabled to get warnings for
functions that are documented, but have no documentation for their parameters
or return value. If set to \c NO, doxygen will only warn about
wrong or incomplete parameter documentation, but not about the absence of
@@ -1287,13 +1297,13 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<docs>
<![CDATA[
The \c WARN_FORMAT tag determines the format of the warning messages that
- doxygen can produce. The string should contain the <code>\$file</code>,
- <code>\$line</code>, and <code>\$text</code>
+ doxygen can produce. The string should contain the <code>\$file</code>,
+ <code>\$line</code>, and <code>\$text</code>
tags, which will be replaced by the file and line number from which the
warning originated and the warning text.
- Optionally the format may contain
- <code>$version</code>, which will be replaced by the version of the file (if it could
- be obtained via \ref cfg_file_version_filter "FILE_VERSION_FILTER")
+ Optionally the format may contain
+ <code>$version</code>, which will be replaced by the version of the file (if it could
+ be obtained via \ref cfg_file_version_filter "FILE_VERSION_FILTER")
]]>
</docs>
</option>
@@ -1301,7 +1311,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<docs>
<![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
+ and error messages should be written. If left blank the output is written
to standard error (`stderr`).
]]>
</docs>
@@ -1311,9 +1321,9 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<option type='list' id='INPUT' format='filedir'>
<docs>
<![CDATA[
- The \c INPUT tag is used to specify the files and/or directories that contain
- documented source files. You may enter file names like
- \c myfile.cpp or directories like \c /usr/src/myproject.
+ The \c INPUT tag is used to specify the files and/or directories that contain
+ documented source files. You may enter file names like
+ \c myfile.cpp or directories like \c /usr/src/myproject.
Separate the files or directories with spaces. See also
\ref cfg_file_patterns "FILE_PATTERNS" and
\ref cfg_extension_mapping "EXTENSION_MAPPING"
@@ -1326,10 +1336,10 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<option type='string' id='INPUT_ENCODING' format='string' defval='UTF-8'>
<docs>
<![CDATA[
- This tag can be used to specify the character encoding of the source files that
+ This tag can be used to specify the character encoding of the source files that
doxygen parses. Internally doxygen uses the UTF-8 encoding.
- Doxygen uses `libiconv` (or the `iconv` built into `libc`) for the transcoding.
- See <a href="https://www.gnu.org/software/libiconv/">the libiconv documentation</a> for
+ Doxygen uses `libiconv` (or the `iconv` built into `libc`) for the transcoding.
+ See <a href="https://www.gnu.org/software/libiconv/">the libiconv documentation</a> for
the list of possible encodings.
]]>
</docs>
@@ -1337,9 +1347,9 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<option type='list' id='FILE_PATTERNS' format='string'>
<docs>
<![CDATA[
- If the value of the \ref cfg_input "INPUT" tag contains directories, you can use the
- \c FILE_PATTERNS tag to specify one or more wildcard patterns
- (like `*.cpp` and `*.h`) to filter out the source-files
+ If the value of the \ref cfg_input "INPUT" tag contains directories, you can use the
+ \c FILE_PATTERNS tag to specify one or more wildcard patterns
+ (like `*.cpp` and `*.h`) to filter out the source-files
in the directories.<br>
Note that for custom extensions or not directly supported extensions you also
need to set \ref cfg_extension_mapping "EXTENSION_MAPPING" for the extension
@@ -1391,6 +1401,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<value name='*.vhdl'/>
<value name='*.ucf'/>
<value name='*.qsf'/>
+ <value name='*.ice'/>
</option>
<option type='bool' id='RECURSIVE' defval='0'>
<docs>
@@ -1413,7 +1424,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<option type='bool' id='EXCLUDE_SYMLINKS' defval='0'>
<docs>
<![CDATA[
- The \c EXCLUDE_SYMLINKS tag can be used to select whether or not files or directories
+ The \c EXCLUDE_SYMLINKS tag can be used to select whether or not files or directories
that are symbolic links (a Unix file system feature) are excluded from the input.
]]>
</docs>
@@ -1424,8 +1435,8 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
If the value of the \ref cfg_input "INPUT" tag contains directories, you can use the
\c EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
certain files from those directories.
- <br>Note that the wildcards are matched
- against the file with absolute path, so to exclude all test directories
+ <br>Note that the wildcards are matched
+ against the file with absolute path, so to exclude all test directories
for example use the pattern `*``/test/``*`
]]>
</docs>
@@ -1433,13 +1444,13 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<option type='list' id='EXCLUDE_SYMBOLS' format='string'>
<docs>
<![CDATA[
- The \c EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
- (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`
- <br>Note that the wildcards are matched against the file with absolute path,
- so to exclude all test directories use the pattern
+ The \c EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+ (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`
+ <br>Note that the wildcards are matched against the file with absolute path,
+ so to exclude all test directories use the pattern
`*``/test/``*`
]]>
</docs>
@@ -1456,7 +1467,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<option type='list' id='EXAMPLE_PATTERNS' format='string'>
<docs>
<![CDATA[
- If the value of the \ref cfg_example_path "EXAMPLE_PATH" tag contains directories,
+ If the value of the \ref cfg_example_path "EXAMPLE_PATH" tag contains directories,
you can use the
\c EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like `*.cpp`
and `*.h`) to filter out the source-files in the directories. If left
@@ -1470,8 +1481,8 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<![CDATA[
If the \c EXAMPLE_RECURSIVE tag is set to \c YES then subdirectories will be
searched for input files to be used with the \ref cmdinclude "\\include" or
- \ref cmddontinclude "\\dontinclude"
- commands irrespective of the value of the \ref cfg_recursive "RECURSIVE" tag.
+ \ref cmddontinclude "\\dontinclude"
+ commands irrespective of the value of the \ref cfg_recursive "RECURSIVE" tag.
]]>
</docs>
</option>
@@ -1479,7 +1490,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<docs>
<![CDATA[
The \c IMAGE_PATH tag can be used to specify one or more files or
- directories that contain images that are to be included in the
+ directories that contain images that are to be included in the
documentation (see the \ref cmdimage "\\image" command).
]]>
</docs>
@@ -1496,9 +1507,9 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
where <code>\<filter\></code>
is the value of the \c INPUT_FILTER tag, and <code>\<input-file\></code> is the name of an
input file. Doxygen will then use the output that the filter program writes
- to standard output. If \ref cfg_filter_patterns "FILTER_PATTERNS" is specified, this tag will be ignored.
- <br>Note that the filter must not add or remove lines; it is applied before the
- code is scanned, but not when the output code is generated. If lines are added
+ to standard output. If \ref cfg_filter_patterns "FILTER_PATTERNS" is specified, this tag will be ignored.
+ <br>Note that the filter must not add or remove lines; it is applied before the
+ code is scanned, but not when the output code is generated. If lines are added
or removed, the anchors will not be placed correctly.
<br>Note that for custom extensions or not directly supported extensions you also
need to set \ref cfg_extension_mapping "EXTENSION_MAPPING" for the extension
@@ -1515,7 +1526,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
filter if there is a match. The filters are a list of the form:
pattern=filter (like `*.cpp=my_cpp_filter`). See \ref cfg_input_filter "INPUT_FILTER" for further
information on how filters are used. If the \c FILTER_PATTERNS tag is empty or if
- none of the patterns match the file name, \ref cfg_input_filter "INPUT_FILTER" is
+ none of the patterns match the file name, \ref cfg_input_filter "INPUT_FILTER" is
applied.
<br>Note that for custom extensions or not directly supported extensions you also
need to set \ref cfg_extension_mapping "EXTENSION_MAPPING" for the extension
@@ -1528,7 +1539,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<![CDATA[
If the \c FILTER_SOURCE_FILES tag is set to \c YES, the input filter (if set using
\ref cfg_input_filter "INPUT_FILTER") will also be used to filter the input
- files that are used for producing the source files to browse
+ files that are used for producing the source files to browse
(i.e. when \ref cfg_source_browser "SOURCE_BROWSER" is set to \c YES).
]]>
</docs>
@@ -1536,10 +1547,10 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<option type='list' id='FILTER_SOURCE_PATTERNS' format='string' depends='FILTER_SOURCE_FILES'>
<docs>
<![CDATA[
- The \c FILTER_SOURCE_PATTERNS tag can be used to specify source filters per
- file pattern. A pattern will override the setting
- for \ref cfg_filter_patterns "FILTER_PATTERN" (if any)
- and it is also possible to disable source filtering for a specific pattern
+ The \c FILTER_SOURCE_PATTERNS tag can be used to specify source filters per
+ file pattern. A pattern will override the setting
+ for \ref cfg_filter_patterns "FILTER_PATTERN" (if any)
+ and it is also possible to disable source filtering for a specific pattern
using `*.ext=` (so without naming a filter).
]]>
</docs>
@@ -1547,9 +1558,9 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<option type='string' id='USE_MDFILE_AS_MAINPAGE' format='string' defval=''>
<docs>
<![CDATA[
- If the \c USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
- is part of the input, its contents will be placed on the main page (`index.html`).
- This can be useful if you have a project on for instance GitHub and want to reuse
+ If the \c USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+ is part of the input, its contents will be placed on the main page (`index.html`).
+ This can be useful if you have a project on for instance GitHub and want to reuse
the introduction page also for the doxygen output.
]]>
</docs>
@@ -1588,7 +1599,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<![CDATA[
If the \c REFERENCED_BY_RELATION tag is set to \c YES
then for each documented entity all documented
- functions referencing it will be listed.
+ functions referencing it will be listed.
]]>
</docs>
</option>
@@ -1597,7 +1608,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<![CDATA[
If the \c REFERENCES_RELATION tag is set to \c YES
then for each documented function all documented entities
- called/used by that function will be listed.
+ called/used by that function will be listed.
]]>
</docs>
</option>
@@ -1605,9 +1616,9 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<docs>
<![CDATA[
If the \c REFERENCES_LINK_SOURCE tag is set to \c YES
- and \ref cfg_source_browser "SOURCE_BROWSER" tag is set to \c YES then the hyperlinks from
+ and \ref cfg_source_browser "SOURCE_BROWSER" tag is set to \c YES then the hyperlinks from
functions in \ref cfg_references_relation "REFERENCES_RELATION" and
- \ref cfg_referenced_by_relation "REFERENCED_BY_RELATION" lists will
+ \ref cfg_referenced_by_relation "REFERENCED_BY_RELATION" lists will
link to the source code. Otherwise they will link to the documentation.
]]>
</docs>
@@ -1615,11 +1626,11 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn"
<option type='bool' id='SOURCE_TOOLTIPS' defval='1' depends='SOURCE_BROWSER'>
<docs>
<![CDATA[
-If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
-source code will show a tooltip with additional information such as prototype,
-brief description and links to the definition and documentation. Since this will
-make the HTML file larger and loading of large files a bit slower, you can opt
-to disable this feature.
+If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+source code will show a tooltip with additional information such as prototype,
+brief description and links to the definition and documentation. Since this will
+make the HTML file larger and loading of large files a bit slower, you can opt
+to disable this feature.
]]>
</docs>
</option>
@@ -1629,8 +1640,8 @@ to disable this feature.
If the \c USE_HTAGS tag is set to \c YES then the references to source code
will point to the HTML generated by the \c htags(1) tool instead of doxygen
built-in source browser. The \c htags tool is part of GNU's global source
- tagging system (see https://www.gnu.org/software/global/global.html). You
- will need version 4.8.6 or higher.
+ tagging system (see https://www.gnu.org/software/global/global.html). You
+ will need version 4.8.6 or higher.
<br>
To use it do the following:
-# Install the latest version of \c global
@@ -1660,10 +1671,10 @@ to disable this feature.
<option type='bool' id='CLANG_ASSISTED_PARSING' setting='USE_LIBCLANG' defval='0'>
<docs>
<![CDATA[
- If the \c CLANG_ASSISTED_PARSING tag is set to \c YES then doxygen will use the
- <a href="http://clang.llvm.org/">clang parser</a> for more accurate parsing
- at the cost of reduced performance. This can be particularly helpful with
- template rich C++ code for which doxygen's built-in parser lacks the
+ If the \c CLANG_ASSISTED_PARSING tag is set to \c YES then doxygen will use the
+ <a href="http://clang.llvm.org/">clang parser</a> for more accurate parsing
+ at the cost of reduced performance. This can be particularly helpful with
+ template rich C++ code for which doxygen's built-in parser lacks the
necessary type information.
@note The availability of this option depends on whether or not doxygen
@@ -1674,9 +1685,9 @@ to disable this feature.
<option type='list' id='CLANG_OPTIONS' format='string' setting='USE_LIBCLANG' depends='CLANG_ASSISTED_PARSING'>
<docs>
<![CDATA[
- If clang assisted parsing is enabled you can provide the compiler with command
- line options that you would normally use when invoking the compiler. Note that
- the include paths will already be set by doxygen for the files and directories
+ If clang assisted parsing is enabled you can provide the compiler with command
+ line options that you would normally use when invoking the compiler. Note that
+ the include paths will already be set by doxygen for the files and directories
specified with \ref cfg_input "INPUT" and \ref cfg_include_path "INCLUDE_PATH".
]]>
</docs>
@@ -1701,7 +1712,7 @@ to disable this feature.
<docs>
<![CDATA[
If the \c ALPHABETICAL_INDEX tag is set to \c YES, an alphabetical index
- of all compounds will be generated. Enable this if the project contains
+ of all compounds will be generated. Enable this if the project contains
a lot of classes, structs, unions or interfaces.
]]>
</docs>
@@ -1709,7 +1720,7 @@ to disable this feature.
<option type='int' id='COLS_IN_ALPHA_INDEX' minval='1' maxval='20' defval='5' depends='ALPHABETICAL_INDEX'>
<docs>
<![CDATA[
- The \c COLS_IN_ALPHA_INDEX tag can be
+ The \c COLS_IN_ALPHA_INDEX tag can be
used to specify the number of columns in which the alphabetical index list will be split.
]]>
</docs>
@@ -1717,9 +1728,9 @@ to disable this feature.
<option type='list' id='IGNORE_PREFIX' format='string' depends='ALPHABETICAL_INDEX'>
<docs>
<![CDATA[
- In case all classes in a project start with a common prefix, all classes will
+ In case all classes in a project start with a common prefix, all classes will
be put under the same header in the alphabetical index.
- The \c IGNORE_PREFIX tag can be used to specify a prefix
+ The \c IGNORE_PREFIX tag can be used to specify a prefix
(or a list of prefixes) that should be ignored while generating the index headers.
]]>
</docs>
@@ -1746,7 +1757,7 @@ to disable this feature.
<option type='string' id='HTML_FILE_EXTENSION' format='string' defval='.html' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- The \c HTML_FILE_EXTENSION tag can be used to specify the file extension for
+ The \c HTML_FILE_EXTENSION tag can be used to specify the file extension for
each generated HTML page (for example: <code>.htm, .php, .asp</code>).
]]>
</docs>
@@ -1754,10 +1765,10 @@ to disable this feature.
<option type='string' id='HTML_HEADER' format='file' defval='' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- The \c HTML_HEADER tag can be used to specify a user-defined HTML
- header file for each generated HTML page.
- If the tag is left blank doxygen will generate a
- standard header.
+ The \c HTML_HEADER tag can be used to specify a user-defined HTML
+ header file for each generated HTML page.
+ If the tag is left blank doxygen will generate a
+ standard header.
<br>
To get valid HTML the header file that
includes any scripts and style sheets that doxygen
@@ -1773,7 +1784,7 @@ doxygen -w html new_header.html new_footer.html new_stylesheet.css YourConfigFil
the default header that doxygen normally uses.
@note The header is subject to change so you typically
- have to regenerate the default header when upgrading to a newer version of
+ have to regenerate the default header when upgrading to a newer version of
doxygen.
]]>
</docs>
@@ -1786,7 +1797,7 @@ doxygen -w html new_header.html new_footer.html new_stylesheet.css YourConfigFil
<dt><code>\$date</code><dd>will be replaced with the current date.
<dt><code>\$year</code><dd>will be replaces with the current year.
<dt><code>\$doxygenversion</code><dd>will be replaced with the version of doxygen
- <dt><code>\$projectname</code><dd>will be replaced with the name of
+ <dt><code>\$projectname</code><dd>will be replaced with the name of
the project (see \ref cfg_project_name "PROJECT_NAME")
<dt><code>\$projectnumber</code><dd>will be replaced with the project number
(see \ref cfg_project_number "PROJECT_NUMBER")
@@ -1794,25 +1805,25 @@ doxygen -w html new_header.html new_footer.html new_stylesheet.css YourConfigFil
description (see \ref cfg_project_brief "PROJECT_BRIEF")
<dt><code>\$projectlogo</code><dd>will be replaced with the project logo
(see \ref cfg_project_logo "PROJECT_LOGO")
- <dt><code>\$treeview</code><dd>will be replaced with links to
- the javascript and style sheets needed for the navigation tree
- (or an empty string when \ref cfg_generate_treeview "GENERATE_TREEVIEW"
+ <dt><code>\$treeview</code><dd>will be replaced with links to
+ the javascript and style sheets needed for the navigation tree
+ (or an empty string when \ref cfg_generate_treeview "GENERATE_TREEVIEW"
is disabled).
- <dt><code>\$search</code><dd>will be replaced with a links to
- the javascript and style sheets needed for the search engine
- (or an empty string when \ref cfg_searchengine "SEARCHENGINE"
+ <dt><code>\$search</code><dd>will be replaced with a links to
+ the javascript and style sheets needed for the search engine
+ (or an empty string when \ref cfg_searchengine "SEARCHENGINE"
is disabled).
- <dt><code>\$mathjax</code><dd>will be replaced with a links to
- the javascript and style sheets needed for the MathJax feature
+ <dt><code>\$mathjax</code><dd>will be replaced with a links to
+ the javascript and style sheets needed for the MathJax feature
(or an empty string when \ref cfg_use_mathjax "USE_MATHJAX" is disabled).
<dt><code>\$relpath^</code><dd>
- If \ref cfg_create_subdirs "CREATE_SUBDIRS" is enabled, the command <code>\$relpath^</code> can be
+ If \ref cfg_create_subdirs "CREATE_SUBDIRS" is enabled, the command <code>\$relpath^</code> can be
used to produce a relative path to the root of the HTML output directory,
e.g. use <code>\$relpath^doxygen.css</code>, to refer to the standard style sheet.
</dl>
- To cope with differences in the layout of the header and footer that depend on
- configuration settings, the header can also contain special blocks that
+ To cope with differences in the layout of the header and footer that depend on
+ configuration settings, the header can also contain special blocks that
will be copied to the output or skipped depending on the configuration.
Such blocks have the following form:
\verbatim
@@ -1841,9 +1852,9 @@ doxygen -w html new_header.html new_footer.html new_stylesheet.css YourConfigFil
when the \ref cfg_project_logo "PROJECT_LOGO" option is not empty.
<dt><code>TITLEAREA</code><dd>Content within this block is copied to the output
when a title is visible at the top of each page. This is the case
- if either \ref cfg_project_name "PROJECT_NAME",
- \ref cfg_project_brief "PROJECT_BRIEF", \ref cfg_project_logo "PROJECT_LOGO"
- is filled in or if both \ref cfg_disable_index "DISABLE_INDEX" and
+ if either \ref cfg_project_name "PROJECT_NAME",
+ \ref cfg_project_brief "PROJECT_BRIEF", \ref cfg_project_logo "PROJECT_LOGO"
+ is filled in or if both \ref cfg_disable_index "DISABLE_INDEX" and
\ref cfg_searchengine "SEARCHENGINE" are enabled.
</dl>
]]>
@@ -1858,12 +1869,12 @@ doxygen -w html new_header.html new_footer.html new_stylesheet.css YourConfigFil
<option type='string' id='HTML_FOOTER' format='file' defval='' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- The \c HTML_FOOTER tag can be used to specify a user-defined HTML footer for
- each generated HTML page.
+ The \c HTML_FOOTER tag can be used to specify a user-defined HTML footer for
+ each generated HTML page.
If the tag is left blank doxygen will generate a standard footer.
- See \ref cfg_html_header "HTML_HEADER" for more information on
- how to generate a default footer and what special commands can be
+ See \ref cfg_html_header "HTML_HEADER" for more information on
+ how to generate a default footer and what special commands can be
used inside the footer.
See also section \ref doxygen_usage for information on how to generate
@@ -1874,17 +1885,17 @@ doxygen -w html new_header.html new_footer.html new_stylesheet.css YourConfigFil
<option type='string' id='HTML_STYLESHEET' format='file' defval='' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- The \c HTML_STYLESHEET tag can be used to specify a user-defined cascading
- style sheet that is used by each HTML page. It can be used to
- fine-tune the look of the HTML output. If left blank doxygen
- will generate a default style sheet.
-
+ The \c HTML_STYLESHEET tag can be used to specify a user-defined cascading
+ style sheet that is used by each HTML page. It can be used to
+ fine-tune the look of the HTML output. If left blank doxygen
+ will generate a default style sheet.
+
See also section \ref doxygen_usage for information on how to generate
the style sheet that doxygen normally uses.
- \note It is recommended to use
+ \note It is recommended to use
\ref cfg_html_extra_stylesheet "HTML_EXTRA_STYLESHEET" instead of this tag,
- as it is more robust and
+ as it is more robust and
this tag (<code>HTML_STYLESHEET</code>) will in the future become obsolete.
]]>
</docs>
@@ -1892,12 +1903,12 @@ doxygen -w html new_header.html new_footer.html new_stylesheet.css YourConfigFil
<option type='list' id='HTML_EXTRA_STYLESHEET' format='file' defval='' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- The \c HTML_EXTRA_STYLESHEET tag can be used to specify additional
- user-defined cascading style sheets that are included after the standard
- style sheets created by doxygen. Using this option one can overrule
- certain style aspects. This is preferred over using \ref cfg_html_stylesheet "HTML_STYLESHEET"
- since it does not replace the standard style sheet and is therefore more
- robust against future updates. Doxygen will copy the style sheet files to
+ The \c HTML_EXTRA_STYLESHEET tag can be used to specify additional
+ user-defined cascading style sheets that are included after the standard
+ style sheets created by doxygen. Using this option one can overrule
+ certain style aspects. This is preferred over using \ref cfg_html_stylesheet "HTML_STYLESHEET"
+ since it does not replace the standard style sheet and is therefore more
+ robust against future updates. Doxygen will copy the style sheet files to
the output directory.
\note The order of the extra style sheet files is of importance (e.g. the last
style sheet in the list overrules the setting of the previous ones in the list).
@@ -1946,12 +1957,12 @@ hr.footer {
<option type='list' id='HTML_EXTRA_FILES' format='file' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- The \c HTML_EXTRA_FILES tag can be used to specify one or more extra images or
- other source files which should be copied to the HTML output directory. Note
- that these files will be copied to the base HTML output directory. Use the
+ The \c HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+ other source files which should be copied to the HTML output directory. Note
+ that these files will be copied to the base HTML output directory. Use the
<code>$relpath^</code> marker in the \ref cfg_html_header "HTML_HEADER" and/or
- \ref cfg_html_footer "HTML_FOOTER" files to load these
- files. In the \ref cfg_html_stylesheet "HTML_STYLESHEET" file, use the file name only. Also note that
+ \ref cfg_html_footer "HTML_FOOTER" files to load these
+ files. In the \ref cfg_html_stylesheet "HTML_STYLESHEET" file, use the file name only. Also note that
the files will be copied as-is; there are no commands or markers available.
]]>
</docs>
@@ -1959,32 +1970,32 @@ hr.footer {
<option type='int' id='HTML_COLORSTYLE_HUE' minval='0' maxval='359' defval='220' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- The \c HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
- Doxygen will adjust the colors in the style sheet and background images
- according to this color. Hue is specified as an angle on a colorwheel,
- see https://en.wikipedia.org/wiki/Hue for more information.
- For instance the value 0 represents red, 60 is yellow, 120 is green,
- 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+ The \c HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+ Doxygen will adjust the colors in the style sheet and background images
+ according to this color. Hue is specified as an angle on a colorwheel,
+ see https://en.wikipedia.org/wiki/Hue for more information.
+ For instance the value 0 represents red, 60 is yellow, 120 is green,
+ 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
]]>
</docs>
</option>
<option type='int' id='HTML_COLORSTYLE_SAT' minval='0' maxval='255' defval='100' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- The \c HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
- the colors in the HTML output. For a value of 0 the output will use
- grayscales only. A value of 255 will produce the most vivid colors.
+ The \c HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+ the colors in the HTML output. For a value of 0 the output will use
+ grayscales only. A value of 255 will produce the most vivid colors.
]]>
</docs>
</option>
<option type='int' id='HTML_COLORSTYLE_GAMMA' minval='40' maxval='240' defval='80' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- The \c HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
- the luminance component of the colors in the HTML output. Values below
- 100 gradually make the output lighter, whereas values above 100 make
- the output darker. The value divided by 100 is the actual gamma applied,
- so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+ The \c HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+ the luminance component of the colors in the HTML output. Values below
+ 100 gradually make the output lighter, whereas values above 100 make
+ the output darker. The value divided by 100 is the actual gamma applied,
+ so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
and 100 does not change the gamma.
]]>
</docs>
@@ -1992,9 +2003,9 @@ hr.footer {
<option type='bool' id='HTML_TIMESTAMP' defval='0' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- If the \c HTML_TIMESTAMP tag is set to \c YES then the footer of
- each generated HTML page will contain the date and time when the page
- was generated. Setting this to \c YES can help to show when doxygen was last run
+ If the \c HTML_TIMESTAMP tag is set to \c YES then the footer of
+ each generated HTML page will contain the date and time when the page
+ was generated. Setting this to \c YES can help to show when doxygen was last run
and thus if the documentation is up to date.
]]>
</docs>
@@ -2002,11 +2013,11 @@ hr.footer {
<option type='bool' id='HTML_DYNAMIC_MENUS' defval='1' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- If the \c HTML_DYNAMIC_MENUS tag is set to \c YES then the generated HTML
- documentation will contain a main index with vertical navigation menus that
- are dynamically created via Javascript. If disabled, the navigation index will consists of
- multiple levels of tabs that are statically embedded in every HTML page.
- Disable this option to support browsers that do not have Javascript, like
+ If the \c HTML_DYNAMIC_MENUS tag is set to \c YES then the generated HTML
+ documentation will contain a main index with vertical navigation menus that
+ are dynamically created via Javascript. If disabled, the navigation index will consists of
+ multiple levels of tabs that are statically embedded in every HTML page.
+ Disable this option to support browsers that do not have Javascript, like
the Qt help browser.
]]>
</docs>
@@ -2016,20 +2027,20 @@ hr.footer {
<![CDATA[
If the \c HTML_DYNAMIC_SECTIONS tag is set to \c YES then the generated HTML
documentation will contain sections that can be hidden and shown after the
- page has loaded.
+ page has loaded.
]]>
</docs>
</option>
<option type='int' id='HTML_INDEX_NUM_ENTRIES' minval='0' maxval='9999' defval='100' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- With \c HTML_INDEX_NUM_ENTRIES one can control the preferred number of
- entries shown in the various tree structured indices initially; the user
- can expand and collapse entries dynamically later on. Doxygen will expand
- the tree to such a level that at most the specified number of entries are
- visible (unless a fully collapsed tree already exceeds this amount).
- So setting the number of entries 1 will produce a full collapsed tree by
- default. 0 is a special value representing an infinite number of entries
+ With \c HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+ entries shown in the various tree structured indices initially; the user
+ can expand and collapse entries dynamically later on. Doxygen will expand
+ the tree to such a level that at most the specified number of entries are
+ visible (unless a fully collapsed tree already exceeds this amount).
+ So setting the number of entries 1 will produce a full collapsed tree by
+ default. 0 is a special value representing an infinite number of entries
and will result in a full expanded tree by default.
]]>
</docs>
@@ -2038,16 +2049,16 @@ hr.footer {
<docs>
<![CDATA[
If the \c GENERATE_DOCSET tag is set to \c YES, additional index files
- will be generated that can be used as input for
- <a href="https://developer.apple.com/tools/xcode/">Apple's Xcode 3
+ will be generated that can be used as input for
+ <a href="https://developer.apple.com/xcode/">Apple's Xcode 3
integrated development environment</a>, introduced with OSX 10.5 (Leopard).
To create a documentation set, doxygen will generate a Makefile in the
HTML output directory. Running \c make will produce the docset in that
- directory and running <code>make install</code> will install the docset in
- <code>~/Library/Developer/Shared/Documentation/DocSets</code>
+ directory and running <code>make install</code> will install the docset in
+ <code>~/Library/Developer/Shared/Documentation/DocSets</code>
so that Xcode will find it at startup. See
- https://developer.apple.com/tools/creatingdocsetswithdoxygen.html for
- more information.
+ https://developer.apple.com/library/archive/featuredarticles/DoxygenXcode/_index.html
+ for more information.
]]>
</docs>
</option>
@@ -2056,7 +2067,7 @@ hr.footer {
<![CDATA[
This tag determines the name 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)
+ documentation sets from a single provider (such as a company or product suite)
can be grouped.
]]>
</docs>
@@ -2066,7 +2077,7 @@ hr.footer {
<![CDATA[
This tag specifies a string that
should uniquely identify the documentation set bundle. This should be a
- reverse domain-name style string, e.g. <code>com.mycompany.MyDocSet</code>.
+ reverse domain-name style string, e.g. <code>com.mycompany.MyDocSet</code>.
Doxygen will append <code>.docset</code> to the name.
]]>
</docs>
@@ -2075,8 +2086,8 @@ hr.footer {
<docs>
<![CDATA[
The \c DOCSET_PUBLISHER_ID
-tag specifies a string that should uniquely identify
-the documentation publisher. This should be a reverse domain-name style
+tag specifies a string that should uniquely identify
+the documentation publisher. This should be a reverse domain-name style
string, e.g. <code>com.mycompany.MyDocSet.documentation</code>.
]]>
</docs>
@@ -2092,14 +2103,14 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<docs>
<![CDATA[
If the \c GENERATE_HTMLHELP tag is set to \c YES then
- doxygen generates three additional HTML index files:
- \c index.hhp, \c index.hhc, and \c index.hhk. The \c index.hhp is a
- project file that can be read by
- <a href="http://www.microsoft.com/en-us/download/details.aspx?id=21138">
+ doxygen generates three additional HTML index files:
+ \c index.hhp, \c index.hhc, and \c index.hhk. The \c index.hhp is a
+ project file that can be read by
+ <a href="https://www.microsoft.com/en-us/download/details.aspx?id=21138">
Microsoft's HTML Help Workshop</a>
on Windows.
<br>
- The HTML Help Workshop contains a compiler that can convert all HTML output
+ The HTML Help Workshop contains a compiler that can convert all HTML output
generated by doxygen into a single compiled HTML file (`.chm`). Compiled
HTML files are now used as the Windows 98 help format, and will replace
the old Windows help format (`.hlp`) on all Windows platforms in the future.
@@ -2123,7 +2134,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<docs>
<![CDATA[
The \c HHC_LOCATION tag can
- be used to specify the location (absolute path including file name) of
+ be used to specify the location (absolute path including file name) of
the HTML help compiler (\c hhc.exe). If non-empty, doxygen will try to run
the HTML help compiler on the generated \c index.hhp.
]]>
@@ -2141,9 +2152,9 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<option type='string' id='CHM_INDEX_ENCODING' format='string' defval='' depends='GENERATE_HTMLHELP'>
<docs>
<![CDATA[
- The \c CHM_INDEX_ENCODING
- is used to encode HtmlHelp index (\c hhk), content (\c hhc) and project file
- content.
+ The \c CHM_INDEX_ENCODING
+ is used to encode HtmlHelp index (\c hhk), content (\c hhc) and project file
+ content.
]]>
</docs>
</option>
@@ -2160,8 +2171,8 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<option type='bool' id='TOC_EXPAND' defval='0' depends='GENERATE_HTMLHELP'>
<docs>
<![CDATA[
- The \c TOC_EXPAND flag can be set to \c YES to add extra items for
- group members to the table of contents of the HTML help documentation
+ The \c TOC_EXPAND flag can be set to \c YES to add extra items for
+ group members to the table of contents of the HTML help documentation
and to the tree view.
]]>
</docs>
@@ -2191,7 +2202,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<![CDATA[
The \c QHP_NAMESPACE tag specifies the namespace to use when generating
Qt Help Project output. For more information please see
- <a href="http://doc.qt.io/qt-4.8/qthelpproject.html#namespace">Qt Help Project / Namespace</a>.
+ <a href="http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace">Qt Help Project / Namespace</a>.
]]>
</docs>
</option>
@@ -2200,7 +2211,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<![CDATA[
The \c QHP_VIRTUAL_FOLDER tag specifies the namespace to use when
generating Qt Help Project output. For more information please see
- <a href="http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders">Qt Help Project / Virtual Folders</a>.
+ <a href="http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders">Qt Help Project / Virtual Folders</a>.
]]>
</docs>
</option>
@@ -2208,7 +2219,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<docs>
<![CDATA[
If the \c QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom filter to add. For more information please see
- <a href="http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+ <a href="http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
]]>
</docs>
</option>
@@ -2217,7 +2228,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<![CDATA[
The \c QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the custom filter to add.
For more information please see
- <a href="http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+ <a href="http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
]]>
</docs>
</option>
@@ -2225,7 +2236,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<docs>
<![CDATA[
The \c QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's filter section matches.
- <a href="http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+ <a href="http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
]]>
</docs>
</option>
@@ -2240,15 +2251,15 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<option type='bool' id='GENERATE_ECLIPSEHELP' defval='0' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- If the \c GENERATE_ECLIPSEHELP tag is set to \c YES, additional index files
- will be generated, together with the HTML files, they form an `Eclipse` help
- plugin.
+ If the \c GENERATE_ECLIPSEHELP tag is set to \c YES, additional index files
+ will be generated, together with the HTML files, they form an `Eclipse` help
+ plugin.
- To install this plugin and make it available under the help contents
- menu in `Eclipse`, the contents of the directory containing the HTML and XML
- files needs to be copied into the plugins directory of eclipse. The name of
- the directory within the plugins directory should be the same as
- the \ref cfg_eclipse_doc_id "ECLIPSE_DOC_ID" value.
+ To install this plugin and make it available under the help contents
+ menu in `Eclipse`, the contents of the directory containing the HTML and XML
+ files needs to be copied into the plugins directory of eclipse. The name of
+ the directory within the plugins directory should be the same as
+ the \ref cfg_eclipse_doc_id "ECLIPSE_DOC_ID" value.
After copying `Eclipse` needs to be restarted before the help appears.
]]>
@@ -2257,8 +2268,8 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<option type='string' id='ECLIPSE_DOC_ID' format='string' defval='org.doxygen.Project' depends='GENERATE_ECLIPSEHELP'>
<docs>
<![CDATA[
- A unique identifier for the `Eclipse` help plugin. When installing the plugin
- the directory name containing the HTML and XML files should also have
+ A unique identifier for the `Eclipse` help plugin. When installing the plugin
+ the directory name containing the HTML and XML files should also have
this name. Each documentation set should have its own identifier.
]]>
</docs>
@@ -2270,8 +2281,8 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
might be necessary to disable the index and replace it with your own.
The \c DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at
top of each HTML page. A value of \c NO enables the index and the
- value \c YES disables it. Since the tabs in the index contain the same
- information as the navigation tree, you can set this option to \c YES if
+ value \c YES disables it. Since the tabs in the index contain the same
+ information as the navigation tree, you can set this option to \c YES if
you also set \ref cfg_generate_treeview "GENERATE_TREEVIEW" to \c YES.
]]>
</docs>
@@ -2294,7 +2305,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
the \ref cfg_project_name "PROJECT_NAME".
Since the tree basically has the same information as the tab index, you could
- consider setting \ref cfg_disable_index "DISABLE_INDEX" to \c YES when
+ consider setting \ref cfg_disable_index "DISABLE_INDEX" to \c YES when
enabling this option.
]]>
</docs>
@@ -2304,7 +2315,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<docs>
<![CDATA[
The \c ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
- that doxygen will group on one line in the generated HTML documentation.
+ that doxygen will group on one line in the generated HTML documentation.
<br>Note that a value of 0 will completely suppress the enum values from
appearing in the overview section.
]]>
@@ -2322,8 +2333,8 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<option type='bool' id='EXT_LINKS_IN_WINDOW' defval='0' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- If the \c EXT_LINKS_IN_WINDOW option is set to \c YES, doxygen will open
- links to external symbols imported via tag files in a separate window.
+ If the \c EXT_LINKS_IN_WINDOW option is set to \c YES, doxygen will open
+ links to external symbols imported via tag files in a separate window.
]]>
</docs>
</option>
@@ -2333,7 +2344,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
Use this tag to change the font size of \f$\mbox{\LaTeX}\f$ formulas included
as images in the HTML documentation.
When you change the font size after a successful doxygen run you need
- to manually remove any `form_*.png` images from the HTML
+ to manually remove any `form_*.png` images from the HTML
output directory to force them to be regenerated.
]]>
</docs>
@@ -2341,23 +2352,23 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<option type='bool' id='FORMULA_TRANSPARENT' defval='1' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- Use the \c FORMULA_TRANSPARENT tag to determine whether or not the images
- generated for formulas are transparent PNGs. Transparent PNGs are
- not supported properly for IE 6.0, but are supported on all modern browsers.
- <br>Note that when changing this option you need to delete any `form_*.png` files
- in the HTML output directory before the changes have effect.
+ Use the \c FORMULA_TRANSPARENT tag to determine whether or not the images
+ generated for formulas are transparent PNGs. Transparent PNGs are
+ not supported properly for IE 6.0, but are supported on all modern browsers.
+ <br>Note that when changing this option you need to delete any `form_*.png` files
+ in the HTML output directory before the changes have effect.
]]>
</docs>
</option>
<option type='bool' id='USE_MATHJAX' defval='0' depends='GENERATE_HTML'>
<docs>
<![CDATA[
- Enable the \c USE_MATHJAX option to render \f$\mbox{\LaTeX}\f$ formulas using MathJax
- (see https://www.mathjax.org) which uses client side Javascript for the
- rendering instead of using pre-rendered bitmaps. Use this if you do not
- have \f$\mbox{\LaTeX}\f$ installed or if you want to formulas look prettier in the HTML
- output. When enabled you may also need to install MathJax separately and
- configure the path to it using the \ref cfg_mathjax_relpath "MATHJAX_RELPATH"
+ Enable the \c USE_MATHJAX option to render \f$\mbox{\LaTeX}\f$ formulas using MathJax
+ (see https://www.mathjax.org) which uses client side Javascript for the
+ rendering instead of using pre-rendered bitmaps. Use this if you do not
+ have \f$\mbox{\LaTeX}\f$ installed or if you want to formulas look prettier in the HTML
+ output. When enabled you may also need to install MathJax separately and
+ configure the path to it using the \ref cfg_mathjax_relpath "MATHJAX_RELPATH"
option.
]]>
</docs>
@@ -2365,7 +2376,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<option type='enum' id='MATHJAX_FORMAT' defval='HTML-CSS' depends='USE_MATHJAX'>
<docs>
<![CDATA[
- When MathJax is enabled you can set the default output format to be used for
+ When MathJax is enabled you can set the default output format to be used for
the MathJax output.
See <a href="http://docs.mathjax.org/en/latest/output.html">the MathJax site</a>
for more details.
@@ -2375,16 +2386,16 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<value name="NativeMML" desc="(i.e. MathML)"/>
<value name="SVG"/>
</option>
- <option type='string' id='MATHJAX_RELPATH' format='string' defval='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/' depends='USE_MATHJAX'>
+ <option type='string' id='MATHJAX_RELPATH' format='string' defval='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/' depends='USE_MATHJAX'>
<docs>
<![CDATA[
- When MathJax is enabled you need to specify the location relative to the
- HTML output directory using the \c MATHJAX_RELPATH option. The destination
- directory should contain the `MathJax.js` script. For instance, if the \c mathjax
- directory is located at the same level as the HTML output directory, then
- \c MATHJAX_RELPATH should be <code>../mathjax</code>. The default value points to
- the MathJax Content Delivery Network so you can quickly see the result without
- installing MathJax. However, it is strongly recommended to install a local
+ When MathJax is enabled you need to specify the location relative to the
+ HTML output directory using the \c MATHJAX_RELPATH option. The destination
+ directory should contain the `MathJax.js` script. For instance, if the \c mathjax
+ directory is located at the same level as the HTML output directory, then
+ \c MATHJAX_RELPATH should be <code>../mathjax</code>. The default value points to
+ the MathJax Content Delivery Network so you can quickly see the result without
+ installing MathJax. However, it is strongly recommended to install a local
copy of MathJax from https://www.mathjax.org before deployment.
]]>
</docs>
@@ -2392,7 +2403,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
<option type='list' id='MATHJAX_EXTENSIONS' format='string' depends='USE_MATHJAX'>
<docs>
<![CDATA[
- The \c MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax extension
+ The \c MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax extension
names that should be enabled during MathJax rendering. For example
\verbatim
MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
@@ -2403,9 +2414,9 @@ MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
<option type='string' id='MATHJAX_CODEFILE' format='string' depends='USE_MATHJAX'>
<docs>
<![CDATA[
- The \c MATHJAX_CODEFILE tag can be used to specify a file with javascript
- pieces of code that will be used on startup of the MathJax code.
- See
+ The \c MATHJAX_CODEFILE tag can be used to specify a file with javascript
+ pieces of code that will be used on startup of the MathJax code.
+ See
<a href="http://docs.mathjax.org/en/latest/output.html">the MathJax site</a>
for more details.
]]>
@@ -2422,7 +2433,7 @@ MATHJAX_CODEFILE = disableRenderer.js
MathJax.Hub.Config({
menuSettings: {
showRenderer: false,
- }
+ }
});
\endverbatim
]]>
@@ -2437,24 +2448,24 @@ MATHJAX_CODEFILE = disableRenderer.js
<docs>
<![CDATA[
When the \c SEARCHENGINE tag is enabled doxygen will generate a search box
- for the HTML output. The underlying search engine uses javascript
+ for the HTML output. The underlying search engine uses javascript
and DHTML and should work on any modern browser. Note that when using
- HTML help (\ref cfg_generate_htmlhelp "GENERATE_HTMLHELP"),
+ HTML help (\ref cfg_generate_htmlhelp "GENERATE_HTMLHELP"),
Qt help (\ref cfg_generate_qhp "GENERATE_QHP"), or docsets
- (\ref cfg_generate_docset "GENERATE_DOCSET") there is already a search
- function so this one should typically be disabled. For large projects
- the javascript based search engine can be slow, then enabling
- \ref cfg_server_based_search "SERVER_BASED_SEARCH" may provide a
- better solution.
+ (\ref cfg_generate_docset "GENERATE_DOCSET") there is already a search
+ function so this one should typically be disabled. For large projects
+ the javascript based search engine can be slow, then enabling
+ \ref cfg_server_based_search "SERVER_BASED_SEARCH" may provide a
+ better solution.
It is possible to search using the keyboard;
to jump to the search box use <code>\<access key\> + S</code> (what the <code>\<access key\></code> is
depends on the OS and browser, but it is typically <code>\<CTRL\></code>, <code>\<ALT\></code>/<code>\<option\></code>, or both).
- Inside the search box use the <code>\<cursor down key\></code> to jump into the search
+ Inside the search box use the <code>\<cursor down key\></code> to jump into the search
results window, the results can be navigated using the <code>\<cursor keys\></code>.
Press <code>\<Enter\></code> to select an item or <code>\<escape\></code> to cancel the search. The
filter options can be selected when the cursor is inside the search box
- by pressing <code>\<Shift\>+\<cursor down\></code>. Also here use the <code>\<cursor keys\></code> to
+ by pressing <code>\<Shift\>+\<cursor down\></code>. Also here use the <code>\<cursor keys\></code> to
select a filter and <code>\<Enter\></code> or <code>\<escape\></code> to activate or cancel the filter option.
]]>
</docs>
@@ -2462,14 +2473,14 @@ MATHJAX_CODEFILE = disableRenderer.js
<option type='bool' id='SERVER_BASED_SEARCH' defval='0' depends='SEARCHENGINE'>
<docs>
<![CDATA[
-When the \c SERVER_BASED_SEARCH tag is enabled the search engine will be
-implemented using a web server instead of a web client using Javascript.
+When the \c SERVER_BASED_SEARCH tag is enabled the search engine will be
+implemented using a web server instead of a web client using Javascript.
-There are two flavors of web server based searching depending on the
-\ref cfg_external_search "EXTERNAL_SEARCH" setting. When disabled,
-doxygen will generate a PHP script for searching and an index file used
-by the script. When \ref cfg_external_search "EXTERNAL_SEARCH" is
-enabled the indexing and searching needs to be provided by external tools.
+There are two flavors of web server based searching depending on the
+\ref cfg_external_search "EXTERNAL_SEARCH" setting. When disabled,
+doxygen will generate a PHP script for searching and an index file used
+by the script. When \ref cfg_external_search "EXTERNAL_SEARCH" is
+enabled the indexing and searching needs to be provided by external tools.
See the section \ref extsearch for details.
]]>
</docs>
@@ -2477,14 +2488,14 @@ See the section \ref extsearch for details.
<option type='bool' id='EXTERNAL_SEARCH' defval='0' depends='SEARCHENGINE'>
<docs>
<![CDATA[
- When \c EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
- script for searching. Instead the search results are written to an XML file
- which needs to be processed by an external indexer. Doxygen will invoke an
- external search engine pointed to by the
- \ref cfg_searchengine_url "SEARCHENGINE_URL" option to obtain
+ When \c EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+ script for searching. Instead the search results are written to an XML file
+ which needs to be processed by an external indexer. Doxygen will invoke an
+ external search engine pointed to by the
+ \ref cfg_searchengine_url "SEARCHENGINE_URL" option to obtain
the search results.
- <br>Doxygen ships with an example indexer (\c doxyindexer) and
- search engine (<code>doxysearch.cgi</code>) which are based on the open source search
+ <br>Doxygen ships with an example indexer (\c doxyindexer) and
+ search engine (<code>doxysearch.cgi</code>) which are based on the open source search
engine library <a href="https://xapian.org/">Xapian</a>.
<br>See the section \ref extsearch for details.
]]>
@@ -2493,11 +2504,11 @@ See the section \ref extsearch for details.
<option type='string' id='SEARCHENGINE_URL' format='string' defval='' depends='SEARCHENGINE'>
<docs>
<![CDATA[
- The \c SEARCHENGINE_URL should point to a search engine hosted by a web server
- which will return the search results when \ref cfg_external_search "EXTERNAL_SEARCH"
+ The \c SEARCHENGINE_URL should point to a search engine hosted by a web server
+ which will return the search results when \ref cfg_external_search "EXTERNAL_SEARCH"
is enabled.
- <br>Doxygen ships with an example indexer (\c doxyindexer) and
- search engine (<code>doxysearch.cgi</code>) which are based on the open source search
+ <br>Doxygen ships with an example indexer (\c doxyindexer) and
+ search engine (<code>doxysearch.cgi</code>) which are based on the open source search
engine library <a href="https://xapian.org/">Xapian</a>.
See the section \ref extsearch for details.
]]>
@@ -2506,9 +2517,9 @@ See the section \ref extsearch for details.
<option type='string' id='SEARCHDATA_FILE' format='file' defval='searchdata.xml' depends='SEARCHENGINE'>
<docs>
<![CDATA[
-When \ref cfg_server_based_search "SERVER_BASED_SEARCH" and
-\ref cfg_external_search "EXTERNAL_SEARCH" are both enabled the unindexed
-search data is written to a file for indexing by an external tool. With the
+When \ref cfg_server_based_search "SERVER_BASED_SEARCH" and
+\ref cfg_external_search "EXTERNAL_SEARCH" are both enabled the unindexed
+search data is written to a file for indexing by an external tool. With the
\c SEARCHDATA_FILE tag the name of this file can be specified.
]]>
</docs>
@@ -2516,10 +2527,10 @@ search data is written to a file for indexing by an external tool. With the
<option type='string' id='EXTERNAL_SEARCH_ID' format='string' defval='' depends='SEARCHENGINE'>
<docs>
<![CDATA[
-When \ref cfg_server_based_search "SERVER_BASED_SEARCH" and
-\ref cfg_external_search "EXTERNAL_SEARCH" are both enabled the
-\c EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
-useful in combination with \ref cfg_extra_search_mappings "EXTRA_SEARCH_MAPPINGS"
+When \ref cfg_server_based_search "SERVER_BASED_SEARCH" and
+\ref cfg_external_search "EXTERNAL_SEARCH" are both enabled the
+\c EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+useful in combination with \ref cfg_extra_search_mappings "EXTRA_SEARCH_MAPPINGS"
to search through multiple projects and redirect the results back to the right project.
]]>
</docs>
@@ -2527,16 +2538,16 @@ to search through multiple projects and redirect the results back to the right p
<option type='list' id='EXTRA_SEARCH_MAPPINGS' format='string' depends='SEARCHENGINE'>
<docs>
<![CDATA[
- The \c EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
- projects other than the one defined by this configuration file, but that are
- all added to the same external search index. Each project needs to have a
- unique id set via \ref cfg_external_search_id "EXTERNAL_SEARCH_ID".
- The search mapping then maps the id of to a relative location where the
- documentation can be found.
+ The \c EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+ projects other than the one defined by this configuration file, but that are
+ all added to the same external search index. Each project needs to have a
+ unique id set via \ref cfg_external_search_id "EXTERNAL_SEARCH_ID".
+ The search mapping then maps the id of to a relative location where the
+ documentation can be found.
- The format is:
+ The format is:
\verbatim
-EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
\endverbatim
]]>
</docs>
@@ -2554,7 +2565,7 @@ EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
<option type='string' id='LATEX_OUTPUT' format='dir' defval='latex' depends='GENERATE_LATEX'>
<docs>
<![CDATA[
- The \c LATEX_OUTPUT tag is used to specify where the \f$\mbox{\LaTeX}\f$
+ The \c LATEX_OUTPUT tag is used to specify where the \f$\mbox{\LaTeX}\f$
docs will be put.
If a relative path is entered the value of \ref cfg_output_directory "OUTPUT_DIRECTORY" will be
put in front of it.
@@ -2564,7 +2575,7 @@ EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
<option type='string' id='LATEX_CMD_NAME' format='file' defval='' depends='GENERATE_LATEX'>
<docs>
<![CDATA[
- The \c LATEX_CMD_NAME tag can be used to specify the \f$\mbox{\LaTeX}\f$ command name to be invoked.
+ The \c LATEX_CMD_NAME tag can be used to specify the \f$\mbox{\LaTeX}\f$ command name to be invoked.
<br>Note that when not enabling \ref cfg_use_pdflatex "USE_PDFLATEX" the default is \c latex when
enabling \ref cfg_use_pdflatex "USE_PDFLATEX" the default is \c pdflatex and when in the later case
\c latex is chosen this is overwritten by \c pdflatex. For specific output languages the default can
@@ -2575,7 +2586,7 @@ EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
<option type='string' id='MAKEINDEX_CMD_NAME' format='file' defval='makeindex' depends='GENERATE_LATEX'>
<docs>
<![CDATA[
- The \c MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+ The \c MAKEINDEX_CMD_NAME tag can be used to specify the command name to
generate index for \f$\mbox{\LaTeX}\f$.
@note This tag is used in the `Makefile` / `make.bat`.
@@ -2586,7 +2597,7 @@ EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
<option type='string' id='LATEX_MAKEINDEX_CMD' defval='\makeindex' depends='GENERATE_LATEX'>
<docs>
<![CDATA[
- The \c LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+ The \c LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
generate index for \f$\mbox{\LaTeX}\f$.
@note This tag is used in the generated output file (`.tex`).
@@ -2618,7 +2629,7 @@ EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
<option type='list' id='EXTRA_PACKAGES' format='string' depends='GENERATE_LATEX'>
<docs>
<![CDATA[
- The \c EXTRA_PACKAGES tag can be used to specify one or more \f$\mbox{\LaTeX}\f$
+ The \c EXTRA_PACKAGES tag can be used to specify one or more \f$\mbox{\LaTeX}\f$
package names that should be included in the \f$\mbox{\LaTeX}\f$ output. The package
can be specified just by its name or with the correct syntax as to be used with the
\f$\mbox{\LaTeX}\f$ `\usepackage` command.
@@ -2626,7 +2637,7 @@ EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
To get the `times` font for instance you can specify :
\verbatim
EXTRA_PACKAGES=times
-or
+or
EXTRA_PACKAGES={times}
\endverbatim
To use the option `intlimits` with the `amsmath` package you can specify:
@@ -2640,21 +2651,21 @@ or
<option type='string' id='LATEX_HEADER' format='file' defval='' depends='GENERATE_LATEX'>
<docs>
<![CDATA[
- The \c LATEX_HEADER tag can be used to specify a personal \f$\mbox{\LaTeX}\f$
- header for the generated \f$\mbox{\LaTeX}\f$ document.
- The header should contain everything until the first chapter.
+ The \c LATEX_HEADER tag can be used to specify a personal \f$\mbox{\LaTeX}\f$
+ header for the generated \f$\mbox{\LaTeX}\f$ document.
+ The header should contain everything until the first chapter.
- If it is left blank doxygen will generate a
- standard header. See section \ref doxygen_usage for information on how to
+ If it is left blank doxygen will generate a
+ standard header. See section \ref doxygen_usage for information on how to
let doxygen write the default header to a separate file.
-
+
<br>Note: Only use a user-defined header if you know what you are doing!
The following commands have a special meaning inside the header:
<code>\$title</code>, <code>\$datetime</code>, <code>\$date</code>,
- <code>\$doxygenversion</code>, <code>\$projectname</code>,
- <code>\$projectnumber</code>, <code>\$projectbrief</code>,
- <code>\$projectlogo</code>.
+ <code>\$doxygenversion</code>, <code>\$projectname</code>,
+ <code>\$projectnumber</code>, <code>\$projectbrief</code>,
+ <code>\$projectlogo</code>.
Doxygen will replace <code>\$title</code> with the empty string, for the replacement values of the
other commands the user is referred to \ref cfg_html_header "HTML_HEADER".
]]>
@@ -2663,14 +2674,14 @@ or
<option type='string' id='LATEX_FOOTER' format='file' defval='' depends='GENERATE_LATEX'>
<docs>
<![CDATA[
- The \c LATEX_FOOTER tag can be used to specify a personal \f$\mbox{\LaTeX}\f$ footer for
- the generated \f$\mbox{\LaTeX}\f$ document. The footer should contain everything after
- the last chapter. If it is left blank doxygen will generate a
+ The \c LATEX_FOOTER tag can be used to specify a personal \f$\mbox{\LaTeX}\f$ footer for
+ the generated \f$\mbox{\LaTeX}\f$ document. The footer should contain everything after
+ the last chapter. If it is left blank doxygen will generate a
standard footer.
- See \ref cfg_latex_header "LATEX_HEADER" for more information on
- how to generate a default footer and what special commands can be
+ See \ref cfg_latex_header "LATEX_HEADER" for more information on
+ how to generate a default footer and what special commands can be
used inside the footer.
-
+
<br>Note: Only use a user-defined footer if you know what you are doing!
]]>
</docs>
@@ -2678,10 +2689,10 @@ or
<option type='list' id='LATEX_EXTRA_STYLESHEET' format='file' defval='' depends='GENERATE_LATEX'>
<docs>
<![CDATA[
- The \c LATEX_EXTRA_STYLESHEET tag can be used to specify additional
- user-defined \f$\mbox{\LaTeX}\f$ style sheets that are included after the standard
- style sheets created by doxygen. Using this option one can overrule
- certain style aspects. Doxygen will copy the style sheet files to
+ The \c LATEX_EXTRA_STYLESHEET tag can be used to specify additional
+ user-defined \f$\mbox{\LaTeX}\f$ style sheets that are included after the standard
+ style sheets created by doxygen. Using this option one can overrule
+ certain style aspects. Doxygen will copy the style sheet files to
the output directory.
\note The order of the extra style sheet files is of importance (e.g. the last
style sheet in the list overrules the setting of the previous ones in the list).
@@ -2702,8 +2713,8 @@ or
<option type='bool' id='PDF_HYPERLINKS' defval='1' depends='GENERATE_LATEX'>
<docs>
<![CDATA[
- If the \c PDF_HYPERLINKS tag is set to \c YES, the \f$\mbox{\LaTeX}\f$ that
- is generated is prepared for conversion to PDF (using \c ps2pdf or \c pdflatex).
+ If the \c PDF_HYPERLINKS tag is set to \c YES, the \f$\mbox{\LaTeX}\f$ that
+ is generated is prepared for conversion to PDF (using \c ps2pdf or \c pdflatex).
The PDF file will
contain links (just like the HTML output) instead of page references.
This makes the output suitable for online browsing using a PDF viewer.
@@ -2715,7 +2726,7 @@ or
<![CDATA[
If the \c USE_PDFLATEX tag is set to \c YES, doxygen will use
\c pdflatex to generate the PDF file directly from the \f$\mbox{\LaTeX}\f$
- files. Set this option to \c YES, to get a higher quality PDF documentation.
+ files. Set this option to \c YES, to get a higher quality PDF documentation.
]]>
</docs>
</option>
@@ -2723,9 +2734,9 @@ or
<docs>
<![CDATA[
If the \c LATEX_BATCHMODE tag is set to \c YES, doxygen will add the \c \\batchmode
- command to the generated \f$\mbox{\LaTeX}\f$ files. This will
- instruct \f$\mbox{\LaTeX}\f$ to keep running if errors occur, instead of
- asking the user for help. This option is also used when generating formulas
+ command to the generated \f$\mbox{\LaTeX}\f$ files. This will
+ instruct \f$\mbox{\LaTeX}\f$ to keep running if errors occur, instead of
+ asking the user for help. This option is also used when generating formulas
in HTML.
]]>
</docs>
@@ -2734,17 +2745,17 @@ or
<docs>
<![CDATA[
If the \c LATEX_HIDE_INDICES tag is set to \c YES then doxygen will not
- include the index chapters (such as File Index, Compound Index, etc.)
- in the output.
+ include the index chapters (such as File Index, Compound Index, etc.)
+ in the output.
]]>
</docs>
</option>
<option type='bool' id='LATEX_SOURCE_CODE' defval='0' depends='GENERATE_LATEX'>
<docs>
<![CDATA[
- If the \c LATEX_SOURCE_CODE tag is set to \c YES then doxygen will include
- source code with syntax highlighting in the \f$\mbox{\LaTeX}\f$ output.
- <br>Note that which sources are shown also depends on other settings
+ If the \c LATEX_SOURCE_CODE tag is set to \c YES then doxygen will include
+ source code with syntax highlighting in the \f$\mbox{\LaTeX}\f$ output.
+ <br>Note that which sources are shown also depends on other settings
such as \ref cfg_source_browser "SOURCE_BROWSER".
]]>
</docs>
@@ -2752,8 +2763,8 @@ or
<option type='string' id='LATEX_BIB_STYLE' format='string' defval='plain' depends='GENERATE_LATEX'>
<docs>
<![CDATA[
- The \c LATEX_BIB_STYLE tag can be used to specify the style to use for the
- bibliography, e.g. \c plainnat, or \c ieeetr.
+ The \c LATEX_BIB_STYLE tag can be used to specify the style to use for the
+ bibliography, e.g. \c plainnat, or \c ieeetr.
See https://en.wikipedia.org/wiki/BibTeX and \ref cmdcite "\\cite"
for more info.
]]>
@@ -2769,6 +2780,16 @@ or
]]>
</docs>
</option>
+ <option type='string' id='LATEX_EMOJI_DIRECTORY' format='dir' defval='' depends='GENERATE_LATEX'>
+ <docs>
+<![CDATA[
+ The \c LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+ path from which the emoji images will be read.
+ If a relative path is entered, it will be relative to the \ref cfg_latex_output "LATEX_OUTPUT"
+ directory. If left blank the \ref cfg_latex_output "LATEX_OUTPUT" directory will be used.
+]]>
+ </docs>
+ </option>
</group>
<group name='RTF' docs='Configuration options related to the RTF output'>
<option type='bool' id='GENERATE_RTF' defval='0'>
@@ -2828,8 +2849,8 @@ or
<docs>
<![CDATA[
Set optional variables used in the generation of an RTF document.
- Syntax is similar to doxygen's configuration file.
- A template extensions file can be generated using
+ Syntax is similar to doxygen's configuration file.
+ A template extensions file can be generated using
<code>doxygen -e rtf extensionFile</code>.
]]>
</docs>
@@ -2859,8 +2880,8 @@ or
<![CDATA[
The \c MAN_OUTPUT tag is used to specify where the man pages will be put.
If a relative path is entered the value of \ref cfg_output_directory "OUTPUT_DIRECTORY" will be
- put in front of it.
- A directory \c man3 will be created inside the directory specified by
+ put in front of it.
+ A directory \c man3 will be created inside the directory specified by
\c MAN_OUTPUT.
]]>
</docs>
@@ -2887,10 +2908,10 @@ or
<option type='bool' id='MAN_LINKS' defval='0' depends='GENERATE_MAN'>
<docs>
<![CDATA[
- If the \c MAN_LINKS tag is set to \c YES and doxygen generates man output,
- then it will generate one additional man file for each entity documented in
- the real man page(s). These additional files only source the real man page,
- but without them the \c man command would be unable to find the correct page.
+ If the \c MAN_LINKS tag is set to \c YES and doxygen generates man output,
+ then it will generate one additional man file for each entity documented in
+ the real man page(s). These additional files only source the real man page,
+ but without them the \c man command would be unable to find the correct page.
]]>
</docs>
</option>
@@ -2901,15 +2922,15 @@ or
<![CDATA[
If the \c GENERATE_XML tag is set to \c YES, doxygen will
generate an XML file that captures the structure of
- the code including all documentation.
+ the code including all documentation.
]]>
</docs>
</option>
<option type='string' id='XML_OUTPUT' format='dir' defval='xml' depends='GENERATE_XML'>
<docs>
<![CDATA[
- The \c XML_OUTPUT tag is used to specify where the XML pages will be put.
- If a relative path is entered the value of \ref cfg_output_directory "OUTPUT_DIRECTORY" will be
+ The \c XML_OUTPUT tag is used to specify where the XML pages will be put.
+ If a relative path is entered the value of \ref cfg_output_directory "OUTPUT_DIRECTORY" will be
put in front of it.
]]>
</docs>
@@ -2929,7 +2950,7 @@ or
<option type='bool' id='GENERATE_DOCBOOK' defval='0'>
<docs>
<![CDATA[
-If the \c GENERATE_DOCBOOK tag is set to \c YES, doxygen will generate Docbook files
+If the \c GENERATE_DOCBOOK tag is set to \c YES, doxygen will generate Docbook files
that can be used to generate PDF.
]]>
</docs>
@@ -2937,8 +2958,8 @@ that can be used to generate PDF.
<option type='string' id='DOCBOOK_OUTPUT' format='dir' defval='docbook' depends='GENERATE_DOCBOOK'>
<docs>
<![CDATA[
-The \c DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
-If a relative path is entered the value of \ref cfg_output_directory "OUTPUT_DIRECTORY" will be put in
+The \c DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+If a relative path is entered the value of \ref cfg_output_directory "OUTPUT_DIRECTORY" will be put in
front of it.
]]>
</docs>
@@ -2961,8 +2982,8 @@ front of it.
If the \c GENERATE_AUTOGEN_DEF tag is set to \c YES, doxygen will
generate an AutoGen Definitions (see http://autogen.sourceforge.net/) file
that captures the structure of the code including all
- documentation. Note that this feature is still experimental
- and incomplete at the moment.
+ documentation. Note that this feature is still experimental
+ and incomplete at the moment.
]]>
</docs>
</option>
@@ -2980,8 +3001,8 @@ If the \c GENERATE_SQLITE3 tag is set to \c YES doxygen will generate a
<option type='string' id='SQLITE3_OUTPUT' format='dir' defval='sqlite3' depends='GENERATE_SQLITE3'>
<docs>
<![CDATA[
-The \c SQLITE3_OUTPUT tag is used to specify where the \c Sqlite3 database will be put.
-If a relative path is entered the value of \ref cfg_output_directory "OUTPUT_DIRECTORY" will be
+The \c SQLITE3_OUTPUT tag is used to specify where the \c Sqlite3 database will be put.
+If a relative path is entered the value of \ref cfg_output_directory "OUTPUT_DIRECTORY" will be
put in front of it.
]]>
</docs>
@@ -2996,7 +3017,7 @@ put in front of it.
If the \c GENERATE_PERLMOD tag is set to \c YES, doxygen will
generate a Perl module file that captures the structure of
the code including all documentation.
- <br>Note that this
+ <br>Note that this
feature is still experimental and incomplete at the
moment.
]]>
@@ -3005,28 +3026,28 @@ put in front of it.
<option type='bool' id='PERLMOD_LATEX' defval='0' depends='GENERATE_PERLMOD'>
<docs>
<![CDATA[
- If the \c PERLMOD_LATEX tag is set to \c YES, doxygen will generate
- the necessary \c Makefile rules, \c Perl scripts and \f$\mbox{\LaTeX}\f$ code to be able
- to generate PDF and DVI output from the Perl module output.
+ If the \c PERLMOD_LATEX tag is set to \c YES, doxygen will generate
+ the necessary \c Makefile rules, \c Perl scripts and \f$\mbox{\LaTeX}\f$ code to be able
+ to generate PDF and DVI output from the Perl module output.
]]>
</docs>
</option>
<option type='bool' id='PERLMOD_PRETTY' defval='1' depends='GENERATE_PERLMOD'>
<docs>
<![CDATA[
- If the \c PERLMOD_PRETTY tag is set to \c YES, the Perl module output will be
- nicely formatted so it can be parsed by a human reader. This is useful
+ If the \c PERLMOD_PRETTY tag is set to \c YES, the Perl module output will be
+ nicely formatted so it can be parsed by a human reader. This is useful
if you want to understand what is going on. On the other hand, if this
tag is set to \c NO, the size of the Perl module output will be much smaller
- and Perl will parse it just the same.
+ and Perl will parse it just the same.
]]>
</docs>
</option>
<option type='string' id='PERLMOD_MAKEVAR_PREFIX' format='string' defval='' depends='GENERATE_PERLMOD'>
<docs>
<![CDATA[
- The names of the make variables in the generated `doxyrules.make` file
- are prefixed with the string contained in \c PERLMOD_MAKEVAR_PREFIX.
+ The names of the make variables in the generated `doxyrules.make` file
+ are prefixed with the string contained in \c PERLMOD_MAKEVAR_PREFIX.
This is useful so different `doxyrules.make` files included by the same
`Makefile` don't overwrite each other's variables.
]]>
@@ -3039,7 +3060,7 @@ put in front of it.
<![CDATA[
If the \c ENABLE_PREPROCESSING tag is set to \c YES, doxygen will
evaluate all C-preprocessor directives found in the sources and include
- files.
+ files.
]]>
</docs>
</option>
@@ -3047,7 +3068,7 @@ put in front of it.
<docs>
<![CDATA[
If the \c MACRO_EXPANSION tag is set to \c YES, doxygen will expand all macro
- names in the source code. If set to \c NO, only conditional
+ names in the source code. If set to \c NO, only conditional
compilation will be performed. Macro expansion can be done in a controlled
way by setting \ref cfg_expand_only_predef "EXPAND_ONLY_PREDEF" to \c YES.
]]>
@@ -3082,10 +3103,10 @@ put in front of it.
<option type='list' id='INCLUDE_FILE_PATTERNS' format='string' depends='ENABLE_PREPROCESSING'>
<docs>
<![CDATA[
- You can use the \c INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
- patterns (like `*.h` and `*.hpp`) to filter out the header-files in the
- directories. If left blank, the patterns specified with \ref cfg_file_patterns "FILE_PATTERNS" will
- be used.
+ You can use the \c INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+ patterns (like `*.h` and `*.hpp`) to filter out the header-files in the
+ directories. If left blank, the patterns specified with \ref cfg_file_patterns "FILE_PATTERNS" will
+ be used.
]]>
</docs>
</option>
@@ -3095,7 +3116,7 @@ put in front of it.
The \c PREDEFINED tag can be used to specify one or more macro names that
are defined before the preprocessor is started (similar to the `-D` option of
e.g. \c gcc). The argument of the tag is a list of macros of the form:
- <code>name</code> or <code>name=definition</code> (no spaces).
+ <code>name</code> or <code>name=definition</code> (no spaces).
If the definition and the \c "=" are omitted, \c "=1" is assumed. To prevent
a macro definition from being undefined via \c \#undef or recursively expanded
use the <code>:=</code> operator instead of the \c = operator.
@@ -3110,18 +3131,18 @@ put in front of it.
this tag can be used to specify a list of macro names that should be expanded.
The macro definition that is found in the sources will be used.
Use the \ref cfg_predefined "PREDEFINED" tag if you want to use a different macro definition that
- overrules the definition found in the source code.
+ overrules the definition found in the source code.
]]>
</docs>
</option>
<option type='bool' id='SKIP_FUNCTION_MACROS' defval='1' depends='ENABLE_PREPROCESSING'>
<docs>
<![CDATA[
- If the \c SKIP_FUNCTION_MACROS tag is set to \c YES then
- doxygen's preprocessor will remove all references to function-like macros that are alone
- on a line, have an all uppercase name, and do not end with a semicolon.
- Such function macros are typically
- used for boiler-plate code, and will confuse the parser if not removed.
+ If the \c SKIP_FUNCTION_MACROS tag is set to \c YES then
+ doxygen's preprocessor will remove all references to function-like macros that are alone
+ on a line, have an all uppercase name, and do not end with a semicolon.
+ Such function macros are typically
+ used for boiler-plate code, and will confuse the parser if not removed.
]]>
</docs>
</option>
@@ -3130,25 +3151,25 @@ put in front of it.
<option type='list' id='TAGFILES' format='file'>
<docs>
<![CDATA[
- The \c TAGFILES tag can be used to specify one or more tag files.
+ The \c TAGFILES tag can be used to specify one or more tag files.
-For each
-tag file the location of the external documentation should be added. The
-format of a tag file without this location is as follows:
+For each
+tag file the location of the external documentation should be added. The
+format of a tag file without this location is as follows:
\verbatim
- TAGFILES = file1 file2 ...
+ TAGFILES = file1 file2 ...
\endverbatim
-Adding location for the tag files is done as follows:
+Adding location for the tag files is done as follows:
\verbatim
- TAGFILES = file1=loc1 "file2 = loc2" ...
+ TAGFILES = file1=loc1 "file2 = loc2" ...
\endverbatim
where `loc1` and `loc2` can be relative or absolute paths or URLs.
See the section \ref external for more information about the use of tag files.
\note
- Each tag file must have a unique name
+ Each tag file must have a unique name
(where the name does \e NOT include the path).
- If a tag file is not located in the directory in which doxygen
+ If a tag file is not located in the directory in which doxygen
is run, you must also specify the path to the tagfile here.
]]>
</docs>
@@ -3158,7 +3179,7 @@ where `loc1` and `loc2` can be relative or absolute paths or URLs.
<![CDATA[
When a file name is specified after \c GENERATE_TAGFILE, doxygen will create
a tag file that is based on the input files it reads.
- See section \ref external for more information about the usage of
+ See section \ref external for more information about the usage of
tag files.
]]>
</docs>
@@ -3184,9 +3205,9 @@ where `loc1` and `loc2` can be relative or absolute paths or URLs.
<option type='bool' id='EXTERNAL_PAGES' defval='1'>
<docs>
<![CDATA[
- If the \c EXTERNAL_PAGES tag is set to \c YES, all external pages will be listed
- in the related pages index. If set to \c NO, only the current project's
- pages will be listed.
+ If the \c EXTERNAL_PAGES tag is set to \c YES, all external pages will be listed
+ in the related pages index. If set to \c NO, only the current project's
+ pages will be listed.
]]>
</docs>
</option>
@@ -3205,19 +3226,19 @@ where `loc1` and `loc2` can be relative or absolute paths or URLs.
<![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.
+ 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='MSCGEN_PATH' format='dir' defval=''>
<docs>
<![CDATA[
- You can define message sequence charts within doxygen comments using the \ref cmdmsc "\\msc"
- command. Doxygen will then run the <a href="http://www.mcternan.me.uk/mscgen/">mscgen tool</a>) to
- produce the chart and insert it in the documentation. The <code>MSCGEN_PATH</code> tag allows you to
- specify the directory where the \c mscgen tool resides. If left empty the tool is assumed to
+ You can define message sequence charts within doxygen comments using the \ref cmdmsc "\\msc"
+ command. Doxygen will then run the <a href="http://www.mcternan.me.uk/mscgen/">mscgen tool</a>) to
+ produce the chart and insert it in the documentation. The <code>MSCGEN_PATH</code> tag allows you to
+ specify the directory where the \c mscgen tool resides. If left empty the tool is assumed to
be found in the default search path.
]]>
</docs>
@@ -3225,9 +3246,9 @@ where `loc1` and `loc2` can be relative or absolute paths or URLs.
<option type='string' id='DIA_PATH' format='dir' defval=''>
<docs>
<![CDATA[
-You can include diagrams made with dia in doxygen documentation. Doxygen will then run
-dia to produce the diagram and insert it in the documentation. The DIA_PATH tag allows
-you to specify the directory where the dia binary resides. If left empty dia is assumed
+You can include diagrams made with dia in doxygen documentation. Doxygen will then run
+dia to produce the diagram and insert it in the documentation. The DIA_PATH tag allows
+you to specify the directory where the dia binary resides. If left empty dia is assumed
to be found in the default search path.
]]>
</docs>
@@ -3245,9 +3266,9 @@ to be found in the default search path.
<docs>
<![CDATA[
If you set the \c HAVE_DOT tag to \c YES then doxygen will assume the \c dot tool is
- available from the \c path. This tool is part of
- <a href="http://www.graphviz.org/">Graphviz</a>, a graph
- visualization toolkit from AT\&T and Lucent Bell Labs. The other options in
+ available from the \c path. This tool is part of
+ <a href="http://www.graphviz.org/">Graphviz</a>, a graph
+ visualization toolkit from AT\&T and Lucent Bell Labs. The other options in
this section have no effect if this option is set to \c NO
]]>
</docs>
@@ -3255,11 +3276,11 @@ to be found in the default search path.
<option type='int' id='DOT_NUM_THREADS' defval='0' minval='0' maxval='32' depends='HAVE_DOT'>
<docs>
<![CDATA[
- The \c DOT_NUM_THREADS specifies the number of \c dot invocations doxygen is
- allowed to run in parallel. When set to \c 0 doxygen will
- base this on the number of processors available in the system. You can set it
- explicitly to a value larger than 0 to get control over the balance
- between CPU load and processing speed.
+ The \c DOT_NUM_THREADS specifies the number of \c dot invocations doxygen is
+ allowed to run in parallel. When set to \c 0 doxygen will
+ base this on the number of processors available in the system. You can set it
+ explicitly to a value larger than 0 to get control over the balance
+ between CPU load and processing speed.
]]>
</docs>
</option>
@@ -3267,11 +3288,11 @@ to be found in the default search path.
<docs>
<![CDATA[
When you want a differently looking font in the dot files that doxygen generates
- you can specify the font name
- using \c DOT_FONTNAME. You need to make sure dot is able to find the font,
- which can be done by putting it in a standard location or by setting the
- \c DOTFONTPATH environment variable or by setting \ref cfg_dot_fontpath "DOT_FONTPATH" to the
- directory containing the font.
+ you can specify the font name
+ using \c DOT_FONTNAME. You need to make sure dot is able to find the font,
+ which can be done by putting it in a standard location or by setting the
+ \c DOTFONTPATH environment variable or by setting \ref cfg_dot_fontpath "DOT_FONTPATH" to the
+ directory containing the font.
]]>
</docs>
</option>
@@ -3286,8 +3307,8 @@ to be found in the default search path.
<docs>
<![CDATA[
By default doxygen will tell \c dot to use the default font as specified with \ref cfg_dot_fontname "DOT_FONTNAME".
- If you specify a
- different font using \ref cfg_dot_fontname "DOT_FONTNAME" you can set the path where \c dot
+ If you specify a
+ different font using \ref cfg_dot_fontname "DOT_FONTNAME" you can set the path where \c dot
can find it using this tag.
]]>
</docs>
@@ -3297,7 +3318,7 @@ to be found in the default search path.
<![CDATA[
If the \c CLASS_GRAPH tag is set to \c YES 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
+ indirect inheritance relations. Setting this tag to \c YES will force
the \ref cfg_class_diagrams "CLASS_DIAGRAMS" tag to \c NO.
]]>
</docs>
@@ -3332,10 +3353,10 @@ to be found in the default search path.
<option type='int' id='UML_LIMIT_NUM_FIELDS' defval='10' minval='0' maxval='100' depends='HAVE_DOT'>
<docs>
<![CDATA[
- If the \ref cfg_uml_look "UML_LOOK" tag is enabled, the fields and methods are shown inside
- the class node. If there are many fields or methods and many nodes the
- graph may become too big to be useful. The \c UML_LIMIT_NUM_FIELDS
- threshold limits the number of items for each type to make the size more
+ If the \ref cfg_uml_look "UML_LOOK" tag is enabled, the fields and methods are shown inside
+ the class node. If there are many fields or methods and many nodes the
+ graph may become too big to be useful. The \c UML_LIMIT_NUM_FIELDS
+ threshold limits the number of items for each type to make the size more
manageable. Set this to 0 for no limit. Note that the threshold may be
exceeded by 50% before the limit is enforced. So when you set the threshold
to 10, up to 15 fields may appear, but if the number exceeds 15, the
@@ -3346,7 +3367,7 @@ to be found in the default search path.
<option type='bool' id='TEMPLATE_RELATIONS' defval='0' depends='HAVE_DOT'>
<docs>
<![CDATA[
- If the \c TEMPLATE_RELATIONS tag is set to \c YES then
+ If the \c TEMPLATE_RELATIONS tag is set to \c YES then
the inheritance and collaboration graphs will show the relations between templates and their instances.
]]>
</docs>
@@ -3355,7 +3376,7 @@ to be found in the default search path.
<docs>
<![CDATA[
If the \c INCLUDE_GRAPH, \ref cfg_enable_preprocessing "ENABLE_PREPROCESSING" and
- \ref cfg_search_includes "SEARCH_INCLUDES"
+ \ref cfg_search_includes "SEARCH_INCLUDES"
tags are set to \c YES then doxygen will generate a graph for each documented file
showing the direct and indirect include dependencies of the file with other
documented files.
@@ -3376,12 +3397,12 @@ to be found in the default search path.
<option type='bool' id='CALL_GRAPH' defval='0' depends='HAVE_DOT'>
<docs>
<![CDATA[
- If the \c CALL_GRAPH tag is set to \c YES then doxygen will
- generate a call dependency graph for every global function or class method.
+ If the \c CALL_GRAPH tag is set to \c YES then doxygen will
+ generate a call dependency graph for every global function or class method.
<br>Note that enabling this option will significantly increase the time of a run.
- So in most cases it will be better to enable call graphs for selected
- functions only using the \ref cmdcallgraph "\\callgraph" command.
- Disabling a call graph can be accomplished by means of the command
+ So in most cases it will be better to enable call graphs for selected
+ functions only using the \ref cmdcallgraph "\\callgraph" command.
+ Disabling a call graph can be accomplished by means of the command
\ref cmdhidecallgraph "\\hidecallgraph".
]]>
</docs>
@@ -3389,12 +3410,12 @@ to be found in the default search path.
<option type='bool' id='CALLER_GRAPH' defval='0' depends='HAVE_DOT'>
<docs>
<![CDATA[
- If the \c CALLER_GRAPH tag is set to \c YES then doxygen will
- generate a caller dependency graph for every global function or class method.
+ If the \c CALLER_GRAPH tag is set to \c YES then doxygen will
+ generate a caller dependency graph for every global function or class method.
<br>Note that enabling this option will significantly increase the time of a run.
- So in most cases it will be better to enable caller graphs for selected
- functions only using the \ref cmdcallergraph "\\callergraph" command.
- Disabling a caller graph can be accomplished by means of the command
+ So in most cases it will be better to enable caller graphs for selected
+ functions only using the \ref cmdcallergraph "\\callergraph" command.
+ Disabling a caller graph can be accomplished by means of the command
\ref cmdhidecallergraph "\\hidecallergraph".
]]>
</docs>
@@ -3402,7 +3423,7 @@ to be found in the default search path.
<option type='bool' id='GRAPHICAL_HIERARCHY' defval='1' depends='HAVE_DOT'>
<docs>
<![CDATA[
- If the \c GRAPHICAL_HIERARCHY tag is set to \c YES then
+ If the \c GRAPHICAL_HIERARCHY tag is set to \c YES then
doxygen will graphical hierarchy of all classes instead of a textual one.
]]>
</docs>
@@ -3410,7 +3431,7 @@ to be found in the default search path.
<option type='bool' id='DIRECTORY_GRAPH' defval='1' depends='HAVE_DOT'>
<docs>
<![CDATA[
- If the \c DIRECTORY_GRAPH tag is set
+ If the \c DIRECTORY_GRAPH tag is set
to \c YES then doxygen will show the dependencies a directory has on other directories
in a graphical way. The dependency relations are determined by the \c \#include
relations between the files in the directories.
@@ -3424,7 +3445,7 @@ to be found in the default search path.
generated by \c dot. For an explanation of the image formats see the section output formats
in the documentation of the \c dot tool
(<a href="http://www.graphviz.org/">Graphviz</a>).
- \note If you choose \c svg you need to set
+ \note If you choose \c svg you need to set
\ref cfg_html_file_extension "HTML_FILE_EXTENSION" to \c xhtml in order to make the SVG files
visible in IE 9+ (other browsers do not have this requirement).
]]>
@@ -3446,10 +3467,10 @@ to be found in the default search path.
<docs>
<![CDATA[
If \ref cfg_dot_image_format "DOT_IMAGE_FORMAT" is set to \c svg, then this option can be set to \c YES to
- enable generation of interactive SVG images that allow zooming and panning.
- <br>Note that this requires a modern browser other than Internet Explorer.
+ enable generation of interactive SVG images that allow zooming and panning.
+ <br>Note that this requires a modern browser other than Internet Explorer.
Tested and working are Firefox, Chrome, Safari, and Opera.
- \note For IE 9+ you need to set \ref cfg_html_file_extension "HTML_FILE_EXTENSION" to \c xhtml in order
+ \note For IE 9+ you need to set \ref cfg_html_file_extension "HTML_FILE_EXTENSION" to \c xhtml in order
to make the SVG files visible. Older versions of IE do not have SVG support.
]]>
</docs>
@@ -3457,15 +3478,15 @@ to be found in the default search path.
<option type='string' id='DOT_PATH' format='dir' defval='' depends='HAVE_DOT'>
<docs>
<![CDATA[
- The \c DOT_PATH tag can be used to specify the path where the \c dot tool can be found.
- If left blank, it is assumed the \c dot tool can be found in the \c path.
+ The \c DOT_PATH tag can be used to specify the path where the \c dot tool can be found.
+ If left blank, it is assumed the \c dot tool can be found in the \c path.
]]>
</docs>
</option>
<option type='list' id='DOTFILE_DIRS' format='dir' depends='HAVE_DOT'>
<docs>
<![CDATA[
- The \c DOTFILE_DIRS tag can be used to specify one or more directories that
+ The \c DOTFILE_DIRS tag can be used to specify one or more directories that
contain dot files that are included in the documentation (see the
\ref cmddotfile "\\dotfile" command).
]]>
@@ -3474,7 +3495,7 @@ to be found in the default search path.
<option type='list' id='MSCFILE_DIRS' format='dir'>
<docs>
<![CDATA[
- The \c MSCFILE_DIRS tag can be used to specify one or more directories that
+ The \c MSCFILE_DIRS tag can be used to specify one or more directories that
contain msc files that are included in the documentation (see the
\ref cmdmscfile "\\mscfile" command).
]]>
@@ -3483,7 +3504,7 @@ to be found in the default search path.
<option type='list' id='DIAFILE_DIRS' format='dir'>
<docs>
<![CDATA[
- The \c DIAFILE_DIRS tag can be used to specify one or more directories that
+ The \c DIAFILE_DIRS tag can be used to specify one or more directories that
contain dia files that are included in the documentation (see the
\ref cmddiafile "\\diafile" command).
]]>
@@ -3492,9 +3513,9 @@ to be found in the default search path.
<option type='string' id='PLANTUML_JAR_PATH' format='dir' 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
- called during a preprocessing step. Doxygen will generate a warning when it encounters a
+ 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
+ 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.
]]>
</docs>
@@ -3502,7 +3523,7 @@ to be found in the default search path.
<option type='string' id='PLANTUML_CFG_FILE' format='file' defval=''>
<docs>
<![CDATA[
- When using plantuml, the \c PLANTUML_CFG_FILE tag can be used to specify a configuration
+ When using plantuml, the \c PLANTUML_CFG_FILE tag can be used to specify a configuration
file for plantuml.
]]>
</docs>
@@ -3511,16 +3532,16 @@ to be found in the default search path.
<docs>
<![CDATA[
When using plantuml, the specified paths are searched for files specified by the \c !include
- statement in a plantuml block.
+ statement in a plantuml block.
]]>
</docs>
</option>
<option type='int' id='DOT_GRAPH_MAX_NODES' minval='0' maxval='10000' defval='50' depends='HAVE_DOT'>
<docs>
<![CDATA[
- The \c DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+ The \c DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
nodes that will be shown in the graph. If the number of nodes in a graph
- becomes larger than this value, doxygen will truncate the graph, which is
+ becomes larger than this value, doxygen will truncate the graph, which is
visualized by representing a node as a red box. Note that doxygen if the number
of direct children of the root node in a graph is already larger than
\c DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
@@ -3531,7 +3552,7 @@ to be found in the default search path.
<option type='int' id='MAX_DOT_GRAPH_DEPTH' minval='0' maxval='1000' defval='0' depends='HAVE_DOT'>
<docs>
<![CDATA[
- The \c MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+ The \c MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
graphs generated by \c dot. A depth value of 3 means that only nodes reachable
from the root by following a path via at most 3 edges will be shown. Nodes
that lay further from the root node will be omitted. Note that setting this
@@ -3545,12 +3566,12 @@ to be found in the default search path.
<docs>
<![CDATA[
Set the \c DOT_TRANSPARENT tag to \c YES to generate images with a transparent
- background. This is disabled by default, because dot on Windows does not
+ background. This is disabled by default, because dot on Windows does not
seem to support this out of the box.
<br>
- Warning: Depending on the platform used,
- enabling this option may lead to badly anti-aliased labels on the edges of
- a graph (i.e. they become hard to read).
+ Warning: Depending on the platform used,
+ enabling this option may lead to badly anti-aliased labels on the edges of
+ a graph (i.e. they become hard to read).
]]>
</docs>
</option>
diff --git a/src/configimpl.h b/src/configimpl.h
index ef8bb21..1594d47 100644
--- a/src/configimpl.h
+++ b/src/configimpl.h
@@ -75,6 +75,7 @@ class ConfigOption
virtual void writeTemplate(FTextStream &t,bool sl,bool upd) = 0;
virtual void compareDoxyfile(FTextStream &t) = 0;
virtual void convertStrToVal() {}
+ virtual void emptyValueToDefault() {}
virtual void substEnvVars() = 0;
virtual void init() {}
@@ -189,6 +190,7 @@ class ConfigString : public ConfigOption
void compareDoxyfile(FTextStream &t);
void substEnvVars();
void init() { m_value = m_defValue.copy(); }
+ void emptyValueToDefault() { if(m_value.isEmpty()) m_value=m_defValue; };
private:
QCString m_value;
@@ -491,6 +493,10 @@ class ConfigImpl
*/
void convertStrToVal();
+ /*! Sets default value in case value is empty
+ */
+ void emptyValueToDefault();
+
/*! Replaces references to environment variable by the actual value
* of the environment variable.
*/
diff --git a/src/configimpl.l b/src/configimpl.l
index 72584d7..b533910 100644
--- a/src/configimpl.l
+++ b/src/configimpl.l
@@ -317,22 +317,71 @@ void ConfigList::writeTemplate(FTextStream &t,bool sl,bool)
void ConfigList::compareDoxyfile(FTextStream &t)
{
- if ( m_value.count() != m_defaultValue.count())
+ const char *p = m_value.first();
+ const char *q = m_defaultValue.first();
+ int defCnt = 0;
+ int valCnt = 0;
+
+ // count non empty elements
+ while (p)
+ {
+ QCString s=p;
+ if (!s.stripWhiteSpace().isEmpty()) valCnt += 1;
+ p = m_value.next();
+ }
+
+ while (q)
+ {
+ QCString s=q;
+ if (!s.stripWhiteSpace().isEmpty()) defCnt += 1;
+ q = m_defaultValue.next();
+ }
+ if ( valCnt != defCnt)
{
writeTemplate(t,TRUE,TRUE);
return;
}
- const char *p = m_value.first();
- const char *q = m_defaultValue.first();
- while (p)
+ // get first non empry element
+ q = m_defaultValue.first();
+ p = m_value.first();
+ QCString sp = p;
+ while (p && sp.stripWhiteSpace().isEmpty())
{
p = m_value.next();
- q = m_defaultValue.next();
- if (QCString(p).stripWhiteSpace() != QCString(q).stripWhiteSpace())
+ sp = p;
+ }
+ QCString sq = q;
+ while (q && sq.stripWhiteSpace().isEmpty())
+ {
+ q = m_value.next();
+ sq = q;
+ }
+ while (p)
+ {
+ // skip empty elements
+ sp = p;
+ while (p && sp.stripWhiteSpace().isEmpty())
+ {
+ p = m_value.next();
+ sp = p;
+ }
+ sq = q;
+ while (q && sq.stripWhiteSpace().isEmpty())
{
- writeTemplate(t,TRUE,TRUE);
- return;
+ q = m_value.next();
+ sq = q;
+ }
+ // be sure we have still an element (p and q have same number of 'filled' elements)
+ if (p)
+ {
+ if (sp.stripWhiteSpace() != sq.stripWhiteSpace())
+ {
+ writeTemplate(t,TRUE,TRUE);
+ return;
+ }
+ p = m_value.next();
+ q = m_defaultValue.next();
}
}
}
@@ -819,7 +868,7 @@ static void readIncludeFile(const char *incName)
}
BEGIN(Start);
}
-<GetStrList>[ \t]+ {
+<GetStrList>[ \t,]+ {
if (!elemStr.isEmpty())
{
//printf("elemStr2=`%s'\n",elemStr.data());
@@ -873,7 +922,7 @@ static void readIncludeFile(const char *incName)
bs.data(),yyLineNr,yyFileName.data());
}
}
-<GetStrList>[^ \#\"\t\r\n]+ {
+<GetStrList>[^ \#\"\t\r\n,]+ {
elemStr+=configStringRecode(yytext,encoding,"UTF-8");
}
<SkipComment>\n { yyLineNr++; BEGIN(Start); }
@@ -934,6 +983,15 @@ void ConfigImpl::convertStrToVal()
option->convertStrToVal();
}
}
+void ConfigImpl::emptyValueToDefault()
+{
+ QListIterator<ConfigOption> it = iterator();
+ ConfigOption *option;
+ for (;(option=it.current());++it)
+ {
+ option->emptyValueToDefault();
+ }
+}
static void substEnvVarsInString(QCString &s)
{
@@ -1205,7 +1263,7 @@ static void cleanUpPaths(QStrList &str)
char *sfp = str.first();
while (sfp)
{
- register char *p = sfp;
+ char *p = sfp;
if (p)
{
char c;
@@ -1805,7 +1863,7 @@ void Config::writeTemplate(FTextStream &t,bool shortList,bool update)
void Config::compareDoxyfile(FTextStream &t)
{
- postProcess(FALSE);
+ postProcess(FALSE, TRUE);
ConfigImpl::instance()->compareDoxyfile(t);
}
@@ -1814,9 +1872,10 @@ bool Config::parse(const char *fileName,bool update)
return ConfigImpl::instance()->parse(fileName,update);
}
-void Config::postProcess(bool clearHeaderAndFooter)
+void Config::postProcess(bool clearHeaderAndFooter, bool compare)
{
ConfigImpl::instance()->substituteEnvironmentVars();
+ if (!compare)ConfigImpl::instance()->emptyValueToDefault();
ConfigImpl::instance()->convertStrToVal();
// avoid bootstrapping issues when the config file already
diff --git a/src/context.cpp b/src/context.cpp
index 33e7dcf..b05ee9f 100644
--- a/src/context.cpp
+++ b/src/context.cpp
@@ -658,7 +658,7 @@ class TranslateContext::Private
{
return theTranslator->trPackages();
}
- else if (m_fortranOpt)
+ else if (m_fortranOpt || m_sliceOpt)
{
return theTranslator->trModules();
}
@@ -689,7 +689,7 @@ class TranslateContext::Private
{
return theTranslator->trPackages();
}
- else if (m_fortranOpt)
+ else if (m_fortranOpt || m_sliceOpt)
{
return theTranslator->trModulesList();
}
@@ -704,7 +704,7 @@ class TranslateContext::Private
{
return theTranslator->trPackageMembers();
}
- else if (m_fortranOpt)
+ else if (m_fortranOpt || m_sliceOpt)
{
return theTranslator->trModulesMembers();
}
@@ -856,6 +856,14 @@ class TranslateContext::Private
{
return theTranslator->trCallerGraph();
}
+ TemplateVariant referencedByRelation() const
+ {
+ return theTranslator->trReferencedBy();
+ }
+ TemplateVariant referencesRelation() const
+ {
+ return theTranslator->trReferences();
+ }
TemplateVariant inheritedFrom() const
{
return theTranslator->trInheritedFrom("@0","@1");
@@ -933,7 +941,8 @@ class TranslateContext::Private
}
TemplateVariant variables() const
{
- return theTranslator->trVariables();
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+ return sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables();
}
TemplateVariant typedefs() const
{
@@ -1112,6 +1121,10 @@ class TranslateContext::Private
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 addtionalInheritedMembers
@@ -1209,6 +1222,7 @@ class TranslateContext::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);
}
TemplateVariant get(const char *n) const
{
@@ -1218,6 +1232,7 @@ class TranslateContext::Private
bool m_javaOpt;
bool m_fortranOpt;
bool m_vhdlOpt;
+ bool m_sliceOpt;
static PropertyMapper<TranslateContext::Private> s_inst;
};
//%% }
@@ -1525,6 +1540,7 @@ class DefinitionContext
case SrcLangExt_SQL: result="sql"; break;
case SrcLangExt_Tcl: result="tcl"; break;
case SrcLangExt_Markdown: result="markdown"; break;
+ case SrcLangExt_Slice: result="slice"; break;
}
return result;
}
@@ -1994,6 +2010,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
d.writeImage(t,g_globals.outputDir,
relPathAsString(),
m_classDef->getOutputFileBase());
+ t << "<div/></map>" << endl;
t << "</div>";
}
break;
@@ -2670,24 +2687,29 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
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("namespaces", &Private::namespaces);
- s_inst.addProperty("constantgroups", &Private::constantgroups);
- s_inst.addProperty("typedefs", &Private::typedefs);
- 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("detailedEnums", &Private::detailedEnums);
- s_inst.addProperty("detailedFunctions", &Private::detailedFunctions);
- s_inst.addProperty("detailedVariables", &Private::detailedVariables);
- s_inst.addProperty("inlineClasses", &Private::inlineClasses);
+ 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)); }
@@ -2722,6 +2744,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
Cachable &cache = getCache();
if (!cache.classes)
{
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
TemplateList *classList = TemplateList::alloc();
if (m_namespaceDef->getClassSDict())
{
@@ -2729,6 +2752,12 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
ClassDef *cd;
for (sdi.toFirst();(cd=sdi.current());++sdi)
{
+ 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));
@@ -2807,6 +2836,14 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
{
return getMemberList(getCache().typedefs,MemberListType_decTypedefMembers,theTranslator->trTypedefs());
}
+ TemplateVariant sequences() const
+ {
+ return getMemberList(getCache().sequences,MemberListType_decSequenceMembers,theTranslator->trSequences());
+ }
+ TemplateVariant dictionaries() const
+ {
+ return getMemberList(getCache().dictionaries,MemberListType_decDictionaryMembers,theTranslator->trDictionaries());
+ }
TemplateVariant enums() const
{
return getMemberList(getCache().enums,MemberListType_decEnumMembers,theTranslator->trEnumerations());
@@ -2821,7 +2858,9 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
}
TemplateVariant variables() const
{
- return getMemberList(getCache().variables,MemberListType_decVarMembers,theTranslator->trVariables());
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+ return getMemberList(getCache().variables,MemberListType_decVarMembers,
+ sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables());
}
TemplateVariant memberGroups() const
{
@@ -2843,6 +2882,14 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
{
return getMemberList(getCache().detailedTypedefs,MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
}
+ TemplateVariant detailedSequences() const
+ {
+ return getMemberList(getCache().detailedSequences,MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation());
+ }
+ TemplateVariant detailedDictionaries() const
+ {
+ return getMemberList(getCache().detailedDictionaries,MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation());
+ }
TemplateVariant detailedEnums() const
{
return getMemberList(getCache().detailedEnums,MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
@@ -2856,7 +2903,10 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
}
TemplateVariant detailedVariables() const
{
- return getMemberList(getCache().detailedVariables,MemberListType_docVarMembers,theTranslator->trVariableDocumentation());
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+ return getMemberList(getCache().detailedVariables,MemberListType_docVarMembers,
+ sliceOpt ? theTranslator->trConstantDocumentation() :
+ theTranslator->trVariableDocumentation());
}
TemplateVariant inlineClasses() const
{
@@ -2889,14 +2939,19 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
{
Cachable(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;
@@ -2961,12 +3016,16 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
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);
@@ -3240,6 +3299,14 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
{
return getMemberList(getCache().typedefs,MemberListType_decTypedefMembers,theTranslator->trTypedefs());
}
+ TemplateVariant sequences() const
+ {
+ return getMemberList(getCache().sequences,MemberListType_decSequenceMembers,theTranslator->trSequences());
+ }
+ TemplateVariant dictionaries() const
+ {
+ return getMemberList(getCache().dictionaries,MemberListType_decDictionaryMembers,theTranslator->trDictionaries());
+ }
TemplateVariant enums() const
{
return getMemberList(getCache().enums,MemberListType_decEnumMembers,theTranslator->trEnumerations());
@@ -3254,7 +3321,9 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
}
TemplateVariant variables() const
{
- return getMemberList(getCache().variables,MemberListType_decVarMembers,theTranslator->trVariables());
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+ return getMemberList(getCache().variables,MemberListType_decVarMembers,
+ sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables());
}
TemplateVariant memberGroups() const
{
@@ -3280,6 +3349,14 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
{
return getMemberList(getCache().detailedTypedefs,MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
}
+ TemplateVariant detailedSequences() const
+ {
+ return getMemberList(getCache().detailedSequences,MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation());
+ }
+ TemplateVariant detailedDictionaries() const
+ {
+ return getMemberList(getCache().detailedDictionaries,MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation());
+ }
TemplateVariant detailedEnums() const
{
return getMemberList(getCache().detailedEnums,MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
@@ -3339,12 +3416,16 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
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;
@@ -3994,6 +4075,10 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
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);
@@ -4918,6 +5003,10 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
}
return TemplateVariant(FALSE);
}
+ TemplateVariant hasReferencedByRelation() const
+ {
+ return TemplateVariant(m_memberDef->hasReferencedByRelation());
+ }
TemplateVariant callGraph() const
{
if (hasCallGraph().toBool())
@@ -4958,6 +5047,14 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
return TemplateVariant("");
}
}
+ TemplateVariant referencedByRelation() const
+ {
+ if (hasReferencedByRelation().toBool())
+ {
+ err("context.cpp: output format not yet supported");
+ }
+ return TemplateVariant("");
+ }
DotCallGraph *getCallerGraph() const
{
Cachable &cache = getCache();
@@ -4978,6 +5075,10 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
}
return TemplateVariant(FALSE);
}
+ TemplateVariant hasReferencesRelation() const
+ {
+ return TemplateVariant(m_memberDef->hasReferencesRelation());
+ }
TemplateVariant callerGraph() const
{
if (hasCallerGraph().toBool())
@@ -5018,6 +5119,14 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
return TemplateVariant("");
}
}
+ TemplateVariant referencesRelation() const
+ {
+ if (hasReferencesRelation().toBool())
+ {
+ err("context.cpp: output format not yet supported");
+ }
+ return TemplateVariant("");
+ }
TemplateVariant type() const
{
return m_memberDef->typeString();
@@ -5494,7 +5603,9 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
}
TemplateVariant variables() const
{
- return getMemberList(getCache().variables,MemberListType_decVarMembers,theTranslator->trVariables());
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+ return getMemberList(getCache().variables,MemberListType_decVarMembers,
+ sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables());
}
TemplateVariant signals() const
{
@@ -6428,7 +6539,7 @@ class NestingContext::Private : public GenericNodeListContext
if (nd->localName().find('@')==-1 &&
(!rootOnly || nd->getOuterScope()==Doxygen::globalScope))
{
- bool hasChildren = namespaceHasVisibleChild(nd,addClasses);
+ bool hasChildren = namespaceHasVisibleChild(nd,addClasses,false,ClassDef::Class);
bool isLinkable = nd->isLinkableInProject();
if (isLinkable || hasChildren)
{
@@ -6943,11 +7054,12 @@ class NamespaceTreeContext::Private
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)
+ else if (fortranOpt || sliceOpt)
{
return theTranslator->trModulesList();
}
diff --git a/src/defargs.l b/src/defargs.l
index 7f1e1bb..52052fa 100644
--- a/src/defargs.l
+++ b/src/defargs.l
@@ -52,6 +52,7 @@
#include <assert.h>
#include <ctype.h>
#include <qregexp.h>
+#include <qcstringlist.h>
#include "defargs.h"
#include "entry.h"
@@ -102,6 +103,19 @@ static int yyread(char *buf,int max_size)
return c;
}
+/* bug_520975 */
+static bool checkSpecialType(QCString &typ, QCString &nam)
+{
+ if (nam == "unsigned" || nam == "signed" ||
+ nam == "volatile" || nam == "const") return TRUE;
+ QCStringList qsl=QCStringList::split(' ',typ);
+ for (uint j=0;j<qsl.count();j++)
+ {
+ if (!(qsl[j] == "unsigned" || qsl[j] == "signed" ||
+ qsl[j] == "volatile" || qsl[j] == "const")) return FALSE;
+ }
+ return TRUE;
+}
%}
B [ \t]
@@ -384,8 +398,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
a->type.mid(sv)=="union" ||
a->type.mid(sv)=="class" ||
a->type.mid(sv)=="typename" ||
- a->type=="const" ||
- a->type=="volatile"
+ checkSpecialType(a->type, a->name)
)
{
a->type = a->type + " " + a->name;
diff --git a/src/defgen.cpp b/src/defgen.cpp
index cd69ab2..a8f89c5 100644
--- a/src/defgen.cpp
+++ b/src/defgen.cpp
@@ -89,20 +89,22 @@ void generateDEFForMember(MemberDef *md,
bool isFunc=FALSE;
switch (md->memberType())
{
- case MemberType_Define: memType="define"; break;
- case MemberType_EnumValue: ASSERT(0); break;
- case MemberType_Property: memType="property"; break;
- case MemberType_Event: memType="event"; break;
- case MemberType_Variable: memType="variable"; break;
- case MemberType_Typedef: memType="typedef"; break;
- case MemberType_Enumeration: memType="enum"; break;
- case MemberType_Interface: memType="interface"; break;
- case MemberType_Service: memType="service"; break;
- case MemberType_Function: memType="function"; isFunc=TRUE; break;
- case MemberType_Signal: memType="signal"; isFunc=TRUE; break;
- case MemberType_Friend: memType="friend"; isFunc=TRUE; break;
- case MemberType_DCOP: memType="dcop"; isFunc=TRUE; break;
- case MemberType_Slot: memType="slot"; isFunc=TRUE; break;
+ case MemberType_Define: memType="define"; break;
+ case MemberType_EnumValue: ASSERT(0); break;
+ case MemberType_Property: memType="property"; break;
+ case MemberType_Event: memType="event"; break;
+ case MemberType_Variable: memType="variable"; break;
+ case MemberType_Typedef: memType="typedef"; break;
+ case MemberType_Enumeration: memType="enum"; break;
+ case MemberType_Interface: memType="interface"; break;
+ case MemberType_Service: memType="service"; break;
+ case MemberType_Sequence: memType="sequence"; break;
+ case MemberType_Dictionary: memType="dictionary"; break;
+ case MemberType_Function: memType="function"; isFunc=TRUE; break;
+ case MemberType_Signal: memType="signal"; isFunc=TRUE; break;
+ case MemberType_Friend: memType="friend"; isFunc=TRUE; break;
+ case MemberType_DCOP: memType="dcop"; isFunc=TRUE; break;
+ case MemberType_Slot: memType="slot"; isFunc=TRUE; break;
}
t << memPrefix << "kind = '" << memType << "';" << endl;
@@ -146,7 +148,7 @@ void generateDEFForMember(MemberDef *md,
stringToArgumentList(md->argsString(),declAl);
QCString fcnPrefix = " " + memPrefix + "param-";
- if (declAl->count()>0)
+ if (defAl && declAl->count()>0)
{
ArgumentListIterator declAli(*declAl);
ArgumentListIterator defAli(*defAl);
@@ -511,6 +513,8 @@ void generateDEFForNamespace(NamespaceDef *nd,FTextStream &t)
generateDEFSection(nd,t,nd->getMemberList(MemberListType_decDefineMembers),"define");
generateDEFSection(nd,t,nd->getMemberList(MemberListType_decProtoMembers),"prototype");
generateDEFSection(nd,t,nd->getMemberList(MemberListType_decTypedefMembers),"typedef");
+ generateDEFSection(nd,t,nd->getMemberList(MemberListType_decSequenceMembers),"sequence");
+ generateDEFSection(nd,t,nd->getMemberList(MemberListType_decDictionaryMembers),"dictionary");
generateDEFSection(nd,t,nd->getMemberList(MemberListType_decEnumMembers),"enum");
generateDEFSection(nd,t,nd->getMemberList(MemberListType_decFuncMembers),"func");
generateDEFSection(nd,t,nd->getMemberList(MemberListType_decVarMembers),"var");
@@ -538,6 +542,8 @@ void generateDEFForFile(FileDef *fd,FTextStream &t)
generateDEFSection(fd,t,fd->getMemberList(MemberListType_decDefineMembers),"define");
generateDEFSection(fd,t,fd->getMemberList(MemberListType_decProtoMembers),"prototype");
generateDEFSection(fd,t,fd->getMemberList(MemberListType_decTypedefMembers),"typedef");
+ generateDEFSection(fd,t,fd->getMemberList(MemberListType_decSequenceMembers),"sequence");
+ generateDEFSection(fd,t,fd->getMemberList(MemberListType_decDictionaryMembers),"dictionary");
generateDEFSection(fd,t,fd->getMemberList(MemberListType_decEnumMembers),"enum");
generateDEFSection(fd,t,fd->getMemberList(MemberListType_decFuncMembers),"func");
generateDEFSection(fd,t,fd->getMemberList(MemberListType_decVarMembers),"var");
diff --git a/src/definition.cpp b/src/definition.cpp
index ec8c0cc..936565d 100644
--- a/src/definition.cpp
+++ b/src/definition.cpp
@@ -42,6 +42,7 @@
#include "filedef.h"
#include "dirdef.h"
#include "pagedef.h"
+#include "bufstr.h"
#define START_MARKER 0x4445465B // DEF[
#define END_MARKER 0x4445465D // DEF]
@@ -716,6 +717,139 @@ void Definition::setInbodyDocumentation(const char *d,const char *inbodyFile,int
_setInbodyDocumentation(d,inbodyFile,inbodyLine);
}
+//---------------------------------------
+
+struct FilterCacheItem
+{
+ portable_off_t filePos;
+ uint fileSize;
+};
+
+/*! Cache for storing the result of filtering a file */
+class FilterCache
+{
+ public:
+ FilterCache() : m_endPos(0) { m_cache.setAutoDelete(TRUE); }
+ bool getFileContents(const QCString &fileName,BufStr &str)
+ {
+ static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
+ QCString filter = getFileFilter(fileName,TRUE);
+ bool usePipe = !filter.isEmpty() && filterSourceFiles;
+ FILE *f=0;
+ const int blockSize = 4096;
+ char buf[blockSize];
+ FilterCacheItem *item=0;
+ if (usePipe && (item = m_cache.find(fileName))) // cache hit: reuse stored result
+ {
+ //printf("getFileContents(%s): cache hit\n",qPrint(fileName));
+ // file already processed, get the results after filtering from the tmp file
+ Debug::print(Debug::FilterOutput,0,"Reusing filter result for %s from %s at offset=%d size=%d\n",
+ qPrint(fileName),qPrint(Doxygen::filterDBFileName),(int)item->filePos,(int)item->fileSize);
+ f = portable_fopen(Doxygen::filterDBFileName,"rb");
+ if (f)
+ {
+ bool success=TRUE;
+ str.resize(item->fileSize+1);
+ if (portable_fseek(f,item->filePos,SEEK_SET)==-1)
+ {
+ err("Failed to seek to position %d in filter database file %s\n",(int)item->filePos,qPrint(Doxygen::filterDBFileName));
+ success=FALSE;
+ }
+ if (success)
+ {
+ int numBytes = fread(str.data(),1,item->fileSize,f);
+ if (numBytes!=item->fileSize)
+ {
+ err("Failed to read %d bytes from position %d in filter database file %s: got %d bytes\n",
+ (int)item->fileSize,(int)item->filePos,qPrint(Doxygen::filterDBFileName),numBytes);
+ success=FALSE;
+ }
+ }
+ str.addChar('\0');
+ fclose(f);
+ return success;
+ }
+ else
+ {
+ err("Failed to open filter database file %s\n",qPrint(Doxygen::filterDBFileName));
+ return FALSE;
+ }
+ }
+ else if (usePipe) // cache miss: filter active but file not previously processed
+ {
+ //printf("getFileContents(%s): cache miss\n",qPrint(fileName));
+ // filter file
+ QCString cmd=filter+" \""+fileName+"\"";
+ Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",qPrint(cmd));
+ f = portable_popen(cmd,"r");
+ FILE *bf = portable_fopen(Doxygen::filterDBFileName,"a+b");
+ FilterCacheItem *item = new FilterCacheItem;
+ item->filePos = m_endPos;
+ if (bf==0)
+ {
+ // handle error
+ err("Error opening filter database file %s\n",qPrint(Doxygen::filterDBFileName));
+ str.addChar('\0');
+ delete item;
+ portable_pclose(f);
+ return FALSE;
+ }
+ // append the filtered output to the database file
+ int size=0;
+ while (!feof(f))
+ {
+ int bytesRead = fread(buf,1,blockSize,f);
+ int bytesWritten = fwrite(buf,1,bytesRead,bf);
+ if (bytesRead!=bytesWritten)
+ {
+ // handle error
+ err("Failed to write to filter database %s. Wrote %d out of %d bytes\n",
+ qPrint(Doxygen::filterDBFileName),bytesWritten,bytesRead);
+ str.addChar('\0');
+ delete item;
+ portable_pclose(f);
+ fclose(bf);
+ return FALSE;
+ }
+ size+=bytesWritten;
+ str.addArray(buf,bytesWritten);
+ }
+ str.addChar('\0');
+ item->fileSize = size;
+ // add location entry to the dictionary
+ m_cache.append(fileName,item);
+ Debug::print(Debug::FilterOutput,0,"Storing new filter result for %s in %s at offset=%d size=%d\n",
+ qPrint(fileName),qPrint(Doxygen::filterDBFileName),(int)item->filePos,(int)item->fileSize);
+ // update end of file position
+ m_endPos += size;
+ portable_pclose(f);
+ fclose(bf);
+ }
+ else // no filtering
+ {
+ // normal file
+ //printf("getFileContents(%s): no filter\n",qPrint(fileName));
+ f = portable_fopen(fileName,"r");
+ while (!feof(f))
+ {
+ int bytesRead = fread(buf,1,blockSize,f);
+ str.addArray(buf,bytesRead);
+ }
+ str.addChar('\0');
+ fclose(f);
+ }
+ return TRUE;
+ }
+ private:
+ SDict<FilterCacheItem> m_cache;
+ portable_off_t m_endPos;
+};
+
+static FilterCache g_filterCache;
+
+//-----------------------------------------
+
+
/*! Reads a fragment of code from file \a fileName starting at
* line \a startLine and ending at line \a endLine (inclusive). The fragment is
* stored in \a result. If FALSE is returned the code fragment could not be
@@ -730,67 +864,60 @@ void Definition::setInbodyDocumentation(const char *d,const char *inbodyFile,int
bool readCodeFragment(const char *fileName,
int &startLine,int &endLine,QCString &result)
{
+ //printf("readCodeFragment(%s,startLine=%d,endLine=%d)\n",fileName,startLine,endLine);
static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
- static int tabSize = Config_getInt(TAB_SIZE);
- //printf("readCodeFragment(%s,%d,%d)\n",fileName,startLine,endLine);
- if (fileName==0 || fileName[0]==0) return FALSE; // not a valid file name
QCString filter = getFileFilter(fileName,TRUE);
- FILE *f=0;
bool usePipe = !filter.isEmpty() && filterSourceFiles;
+ int tabSize = Config_getInt(TAB_SIZE);
SrcLangExt lang = getLanguageFromFileName(fileName);
- if (!usePipe) // no filter given or wanted
- {
- f = portable_fopen(fileName,"r");
- }
- else // use filter
- {
- QCString cmd=filter+" \""+fileName+"\"";
- Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",qPrint(cmd));
- f = portable_popen(cmd,"r");
- }
- bool found = lang==SrcLangExt_VHDL ||
- lang==SrcLangExt_Tcl ||
- lang==SrcLangExt_Python ||
- lang==SrcLangExt_Fortran;
+ const int blockSize = 4096;
+ BufStr str(blockSize);
+ g_filterCache.getFileContents(fileName,str);
+
+ bool found = lang==SrcLangExt_VHDL ||
+ lang==SrcLangExt_Tcl ||
+ lang==SrcLangExt_Python ||
+ lang==SrcLangExt_Fortran;
// for VHDL, TCL, Python, and Fortran no bracket search is possible
- if (f)
+ char *p=str.data();
+ if (p)
{
int c=0;
int col=0;
int lineNr=1;
// skip until the startLine has reached
- while (lineNr<startLine && !feof(f))
+ while (lineNr<startLine && *p)
{
- while ((c=fgetc(f))!='\n' && c!=EOF) /* skip */;
- lineNr++;
+ while ((c=*p++)!='\n' && c!=0) /* skip */;
+ lineNr++;
if (found && c == '\n') c = '\0';
}
- if (!feof(f))
+ if (*p)
{
// skip until the opening bracket or lonely : is found
char cn=0;
- while (lineNr<=endLine && !feof(f) && !found)
+ while (lineNr<=endLine && *p && !found)
{
int pc=0;
- while ((c=fgetc(f))!='{' && c!=':' && c!=EOF) // } so vi matching brackets has no problem
+ while ((c=*p++)!='{' && c!=':' && c!=0)
{
//printf("parsing char `%c'\n",c);
- if (c=='\n')
+ if (c=='\n')
{
- lineNr++,col=0;
+ lineNr++,col=0;
}
- else if (c=='\t')
+ else if (c=='\t')
{
col+=tabSize - (col%tabSize);
}
else if (pc=='/' && c=='/') // skip single line comment
{
- while ((c=fgetc(f))!='\n' && c!=EOF) pc=c;
+ while ((c=*p++)!='\n' && c!=0) pc=c;
if (c=='\n') lineNr++,col=0;
}
else if (pc=='/' && c=='*') // skip C style comment
{
- while (((c=fgetc(f))!='/' || pc!='*') && c!=EOF)
+ while (((c=*p++)!='/' || pc!='*') && c!=0)
{
if (c=='\n') lineNr++,col=0;
pc=c;
@@ -804,16 +931,16 @@ bool readCodeFragment(const char *fileName,
}
if (c==':')
{
- cn=fgetc(f);
+ cn=*p++;
if (cn!=':') found=TRUE;
}
- else if (c=='{') // } so vi matching brackets has no problem
+ else if (c=='{')
{
found=TRUE;
}
}
//printf(" -> readCodeFragment(%s,%d,%d) lineNr=%d\n",fileName,startLine,endLine,lineNr);
- if (found)
+ if (found)
{
// For code with more than one line,
// fill the line with spaces until we are at the right column
@@ -827,57 +954,47 @@ bool readCodeFragment(const char *fileName,
// copy until end of line
if (c) result+=c;
startLine=lineNr;
- if (c==':')
+ if (c==':')
{
result+=cn;
if (cn=='\n') lineNr++;
}
- const int maxLineLength=4096;
- char lineStr[maxLineLength];
- do
+ char lineStr[blockSize];
+ do
{
//printf("reading line %d in range %d-%d\n",lineNr,startLine,endLine);
int size_read;
- do
+ do
{
// read up to maxLineLength-1 bytes, the last byte being zero
- char *p = fgets(lineStr, maxLineLength,f);
- //printf(" read %s",p);
- if (p)
+ int i=0;
+ while ((c=*p++) && i<blockSize-1)
{
- size_read=qstrlen(p);
+ lineStr[i++]=c;
+ if (c=='\n') break; // stop at end of the line
}
- else // nothing read
- {
- size_read=-1;
- lineStr[0]='\0';
- }
- result+=lineStr;
- } while (size_read == (maxLineLength-1));
-
- lineNr++;
- } while (lineNr<=endLine && !feof(f));
+ lineStr[i]=0;
+ size_read=i;
+ result+=lineStr; // append line to the output
+ } while (size_read == (blockSize-1)); // append more if line does not fit in buffer
+ lineNr++;
+ } while (lineNr<=endLine && *p);
// strip stuff after closing bracket
int newLineIndex = result.findRev('\n');
int braceIndex = result.findRev('}');
- if (braceIndex > newLineIndex)
+ if (braceIndex > newLineIndex)
{
result.truncate(braceIndex+1);
}
endLine=lineNr-1;
}
}
- if (usePipe)
+ if (usePipe)
{
- portable_pclose(f);
Debug::print(Debug::FilterOutput, 0, "Filter output\n");
Debug::print(Debug::FilterOutput,0,"-------------\n%s\n-------------\n",qPrint(result));
}
- else
- {
- fclose(f);
- }
}
result = transcodeCharacterStringToUTF8(result);
if (!result.isEmpty() && result.at(result.length()-1)!='\n') result += "\n";
@@ -1329,18 +1446,12 @@ void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName,
void Definition::writeSourceReffedBy(OutputList &ol,const char *scopeName)
{
- if (Config_getBool(REFERENCED_BY_RELATION))
- {
- _writeSourceRefList(ol,scopeName,theTranslator->trReferencedBy(),m_impl->sourceRefByDict,FALSE);
- }
+ _writeSourceRefList(ol,scopeName,theTranslator->trReferencedBy(),m_impl->sourceRefByDict,FALSE);
}
void Definition::writeSourceRefs(OutputList &ol,const char *scopeName)
{
- if (Config_getBool(REFERENCES_RELATION))
- {
- _writeSourceRefList(ol,scopeName,theTranslator->trReferences(),m_impl->sourceRefsDict,TRUE);
- }
+ _writeSourceRefList(ol,scopeName,theTranslator->trReferences(),m_impl->sourceRefsDict,TRUE);
}
bool Definition::hasDocumentation() const
@@ -1527,13 +1638,21 @@ void Definition::mergeRefItems(Definition *d)
m_impl->xrefListItems->setAutoDelete(TRUE);
}
QListIterator<ListItemInfo> slii(*xrefList);
+ QListIterator<ListItemInfo> mlii(*m_impl->xrefListItems);
ListItemInfo *lii;
+ ListItemInfo *mii;
for (slii.toFirst();(lii=slii.current());++slii)
{
- if (_getXRefListId(lii->type)==-1)
+ bool found = false;
+ for (mlii.toFirst();(mii=mlii.current());++mlii)
{
- m_impl->xrefListItems->append(new ListItemInfo(*lii));
+ if ((qstrcmp(lii->type,mii->type)==0) && (lii->itemId == mii->itemId))
+ {
+ found = true;
+ break;
+ }
}
+ if (!found) m_impl->xrefListItems->append(new ListItemInfo(*lii));
}
}
}
diff --git a/src/diagram.cpp b/src/diagram.cpp
index 667aa85..83e42b3 100644
--- a/src/diagram.cpp
+++ b/src/diagram.cpp
@@ -1380,7 +1380,5 @@ void ClassDiagram::writeImage(FTextStream &t,const char *path,
#define IMAGE_EXT ".png"
image.save((QCString)path+"/"+fileName+IMAGE_EXT);
Doxygen::indexList->addImageFile(QCString(fileName)+IMAGE_EXT);
-
- if (generateMap) t << "</map>" << endl;
}
diff --git a/src/dirdef.cpp b/src/dirdef.cpp
index 6631ed7..7294e4f 100644
--- a/src/dirdef.cpp
+++ b/src/dirdef.cpp
@@ -485,8 +485,14 @@ void DirDef::writeDocumentation(OutputList &ol)
case LayoutDocEntry::NamespaceNestedNamespaces:
case LayoutDocEntry::NamespaceNestedConstantGroups:
case LayoutDocEntry::NamespaceClasses:
+ case LayoutDocEntry::NamespaceInterfaces:
+ case LayoutDocEntry::NamespaceStructs:
+ case LayoutDocEntry::NamespaceExceptions:
case LayoutDocEntry::NamespaceInlineClasses:
case LayoutDocEntry::FileClasses:
+ case LayoutDocEntry::FileInterfaces:
+ case LayoutDocEntry::FileStructs:
+ case LayoutDocEntry::FileExceptions:
case LayoutDocEntry::FileNamespaces:
case LayoutDocEntry::FileConstantGroups:
case LayoutDocEntry::FileIncludes:
diff --git a/src/docbookgen.cpp b/src/docbookgen.cpp
index 785dee8..97c602d 100644
--- a/src/docbookgen.cpp
+++ b/src/docbookgen.cpp
@@ -70,52 +70,6 @@
#endif
//------------------
-class DocbookSectionMapper : public QIntDict<char>
-{
- public:
- DocbookSectionMapper() : QIntDict<char>(47)
- {
- insert(MemberListType_pubTypes,"public-type");
- insert(MemberListType_pubMethods,"public-func");
- insert(MemberListType_pubAttribs,"public-attrib");
- insert(MemberListType_pubSlots,"public-slot");
- insert(MemberListType_signals,"signal");
- insert(MemberListType_dcopMethods,"dcop-func");
- insert(MemberListType_properties,"property");
- insert(MemberListType_events,"event");
- insert(MemberListType_pubStaticMethods,"public-static-func");
- insert(MemberListType_pubStaticAttribs,"public-static-attrib");
- insert(MemberListType_proTypes,"protected-type");
- insert(MemberListType_proMethods,"protected-func");
- insert(MemberListType_proAttribs,"protected-attrib");
- insert(MemberListType_proSlots,"protected-slot");
- insert(MemberListType_proStaticMethods,"protected-static-func");
- insert(MemberListType_proStaticAttribs,"protected-static-attrib");
- insert(MemberListType_pacTypes,"package-type");
- insert(MemberListType_pacMethods,"package-func");
- insert(MemberListType_pacAttribs,"package-attrib");
- insert(MemberListType_pacStaticMethods,"package-static-func");
- insert(MemberListType_pacStaticAttribs,"package-static-attrib");
- insert(MemberListType_priTypes,"private-type");
- insert(MemberListType_priMethods,"private-func");
- insert(MemberListType_priAttribs,"private-attrib");
- insert(MemberListType_priSlots,"private-slot");
- insert(MemberListType_priStaticMethods,"private-static-func");
- insert(MemberListType_priStaticAttribs,"private-static-attrib");
- insert(MemberListType_friends,"friend");
- insert(MemberListType_related,"related");
- insert(MemberListType_decDefineMembers,"define");
- insert(MemberListType_decProtoMembers,"prototype");
- insert(MemberListType_decTypedefMembers,"typedef");
- insert(MemberListType_decEnumMembers,"enum");
- insert(MemberListType_decFuncMembers,"func");
- insert(MemberListType_decVarMembers,"var");
- }
-};
-
-static DocbookSectionMapper g_docbookSectionMapper;
-
-
inline void writeDocbookString(FTextStream &t,const char *s)
{
t << convertToDocBook(s);
@@ -149,20 +103,6 @@ inline void writeDocbookCodeString(FTextStream &t,const char *s, int &col)
}
}
-static void writeDocbookHeaderMainpage(FTextStream &t, QCString &pageName)
-{
- t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;;
- t << "<chapter xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"";
- if (!pageName.isEmpty()) t << " xml:id=\"_" << pageName << "\"";
- t << ">" << endl;
-}
-
-static void writeDocbookHeader_ID(FTextStream &t, QCString id)
-{
- t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;;
- t << "<section xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:id=\"_" << id << "\">" << endl;
-}
-
static void addIndexTerm(FTextStream &t, QCString prim, QCString sec = "")
{
t << "<indexterm><primary>";
@@ -187,25 +127,6 @@ void writeDocbookLink(FTextStream &t,const char * /*extRef*/,const char *compoun
t << "</link>";
}
-class TextGeneratorDocbookImpl : public TextGeneratorIntf
-{
- public:
- TextGeneratorDocbookImpl(FTextStream &t): m_t(t) {}
- void writeString(const char *s,bool /*keepSpaces*/) const
- {
- writeDocbookString(m_t,s);
- }
- void writeBreak(int) const {}
- void writeLink(const char *extRef,const char *file,
- const char *anchor,const char *text
- ) const
- {
- writeDocbookLink(m_t,extRef,file,anchor,text,0);
- }
- private:
- FTextStream &m_t;
-};
-
DocbookCodeGenerator::DocbookCodeGenerator(FTextStream &t) : m_lineNumber(-1), m_col(0),
m_insideCodeLine(FALSE), m_insideSpecialHL(FALSE)
{
@@ -328,2074 +249,6 @@ void DocbookCodeGenerator::endCodeFragment()
m_t << "</computeroutput></literallayout>" << endl;
}
-static void writeTemplateArgumentList(ArgumentList *al,
- FTextStream &t,
- Definition *scope,
- FileDef *fileScope,
- int indent)
-{
- QCString indentStr;
- indentStr.fill(' ',indent);
- if (al)
- {
- t << indentStr << "<templateparamlist>" << endl;
- ArgumentListIterator ali(*al);
- Argument *a;
- for (ali.toFirst();(a=ali.current());++ali)
- {
- t << indentStr << " <param>" << endl;
- if (!a->type.isEmpty())
- {
- t << indentStr << " <type>";
- linkifyText(TextGeneratorDocbookImpl(t),scope,fileScope,0,a->type);
- t << "</type>" << endl;
- }
- if (!a->name.isEmpty())
- {
- t << indentStr << " <declname>" << a->name << "</declname>" << endl;
- t << indentStr << " <defname>" << a->name << "</defname>" << endl;
- }
- if (!a->defval.isEmpty())
- {
- t << indentStr << " <defval>";
- linkifyText(TextGeneratorDocbookImpl(t),scope,fileScope,0,a->defval);
- t << "</defval>" << endl;
- }
- t << indentStr << " </param>" << endl;
- }
- t << indentStr << "</templateparamlist>" << endl;
- }
-}
-
-static void writeTemplateList(ClassDef *cd,FTextStream &t)
-{
- writeTemplateArgumentList(cd->templateArguments(),t,cd,0,4);
-}
-
-static void writeDocbookDocBlock(FTextStream &t,
- const QCString &fileName,
- int lineNr,
- Definition *scope,
- MemberDef * md,
- const QCString &text)
-{
- QCString stext = text.stripWhiteSpace();
- if (stext.isEmpty()) return;
- // convert the documentation string into an abstract syntax tree
- DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,text,FALSE,FALSE);
- // create a code generator
- DocbookCodeGenerator *docbookCodeGen = new DocbookCodeGenerator(t);
- // create a parse tree visitor for Docbook
- DocbookDocVisitor *visitor = new DocbookDocVisitor(t,*docbookCodeGen);
- // visit all nodes
- root->accept(visitor);
- // clean up
- delete visitor;
- delete docbookCodeGen;
- delete root;
-}
-
-void writeDocbookCodeBlock(FTextStream &t,FileDef *fd)
-{
- ParserInterface *pIntf=Doxygen::parserManager->getParser(fd->getDefFileExtension());
- SrcLangExt langExt = getLanguageFromFileName(fd->getDefFileExtension());
- pIntf->resetCodeParserState();
- DocbookCodeGenerator *docbookGen = new DocbookCodeGenerator(t);
- pIntf->parseCode(*docbookGen, // codeOutIntf
- 0, // scopeName
- fileToString(fd->absFilePath(),Config_getBool(FILTER_SOURCE_FILES)),
- langExt, // lang
- FALSE, // isExampleBlock
- 0, // exampleName
- fd, // fileDef
- -1, // startLine
- -1, // endLine
- FALSE, // inlineFragement
- 0, // memberDef
- TRUE // showLineNumbers
- );
- docbookGen->finish();
- delete docbookGen;
-}
-
-static QCString classOutputFileBase(ClassDef *cd)
-{
- //static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES);
- //if (inlineGroupedClasses && cd->partOfGroups()!=0)
- return cd->getOutputFileBase();
- //else
- // return cd->getOutputFileBase();
-}
-
-static QCString memberOutputFileBase(MemberDef *md)
-{
- //static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES);
- //if (inlineGroupedClasses && md->getClassDef() && md->getClassDef()->partOfGroups()!=0)
- // return md->getClassDef()->getDocbookOutputFileBase();
- //else
- // return md->getOutputFileBase();
- return md->getOutputFileBase();
-}
-
-static void generateTOC(FTextStream &t, PageDef *pd)
-{
- if (pd->localToc().isDocbookEnabled())
- {
- t << " <toc>" << endl;
- t << " <title>" << theTranslator->trRTFTableOfContents() << "</title>" << endl;
- SectionDict *sectionDict = pd->getSectionDict();
- SDict<SectionInfo>::Iterator li(*sectionDict);
- SectionInfo *si;
- int level=1,l;
- bool inLi[5]={ FALSE, FALSE, FALSE, FALSE, FALSE };
- int maxLevel = pd->localToc().docbookLevel();
- for (li.toFirst();(si=li.current());++li)
- {
- if (si->type==SectionInfo::Section ||
- si->type==SectionInfo::Subsection ||
- si->type==SectionInfo::Subsubsection ||
- si->type==SectionInfo::Paragraph)
- {
- //printf(" level=%d title=%s\n",level,si->title.data());
- int nextLevel = (int)si->type;
- if (nextLevel>level)
- {
- for (l=level;l<nextLevel;l++)
- {
- if (l < maxLevel) t << " <tocdiv>" << endl;
- }
- }
- else if (nextLevel<level)
- {
- for (l=level;l>nextLevel;l--)
- {
- inLi[l]=FALSE;
- if (l <= maxLevel) t << " </tocdiv>" << endl;
- }
- }
- if (nextLevel <= maxLevel)
- {
- QCString titleDoc = convertToDocBook(si->title);
- t << " <tocentry>" << (si->title.isEmpty()?si->label:titleDoc) << "</tocentry>" << endl;
- }
- inLi[nextLevel]=TRUE;
- level = nextLevel;
- }
- }
- t << " </toc>" << endl;
- }
-}
-
-static void generateSourceRefList(FTextStream &t,const char *scopeName, const QCString &text,MemberSDict *members, Definition *def)
-{
- static bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
- static bool refLinkSource = Config_getBool(REFERENCES_LINK_SOURCE);
-
- if (members)
- {
- members->sort();
-
- t << "<formalpara><title>" << convertToDocBook(text) << "</title><para>";
-
- QCString ldefLine=theTranslator->trWriteList(members->count());
-
- QRegExp marker("@[0-9]+");
- int index=0,newIndex,matchLen;
- // now replace all markers in inheritLine with links to the classes
- while ((newIndex=marker.match(ldefLine,index,&matchLen))!=-1)
- {
- bool ok;
- t << convertToDocBook(ldefLine.mid(index,newIndex-index));
- uint entryIndex = ldefLine.mid(newIndex+1,matchLen-1).toUInt(&ok);
- MemberDef *md=members->at(entryIndex);
- if (ok && md)
- {
- QCString scope=md->getScopeString();
- QCString name=md->name();
- //printf("class=%p scope=%s scopeName=%s\n",md->getClassDef(),scope.data(),scopeName);
- if (!scope.isEmpty() && scope!=scopeName)
- {
- name.prepend(scope+getLanguageSpecificSeparator(def->getLanguage()));
- }
- if (!md->isObjCMethod() &&
- (md->isFunction() || md->isSlot() ||
- md->isPrototype() || md->isSignal()
- )
- )
- {
- name+="()";
- }
- //Definition *d = md->getOutputFileBase();
- //if (d==Doxygen::globalScope) d=md->getBodyDef();
- if (sourceBrowser &&
- !(md->isLinkable() && !refLinkSource) &&
- md->getStartBodyLine()!=-1 &&
- md->getBodyDef()
- )
- {
- //printf("md->getBodyDef()=%p global=%p\n",md->getBodyDef(),Doxygen::globalScope);
-
- const int maxLineNrStr = 10;
- char anchorStr[maxLineNrStr];
- qsnprintf(anchorStr,maxLineNrStr,"l%05d",md->getStartBodyLine());
- //printf("Write object link to %s\n",md->getBodyDef()->getSourceFileBase().data());
- t << convertToDocBook(name);
- // or
- // ol.writeObjectLink(0,md->getBodyDef()->getSourceFileBase(),anchorStr,name);
- }
- else if (md->isLinkable() /*&& d && d->isLinkable()*/)
- {
- t << convertToDocBook(name);
- // or
- // ol.writeObjectLink(md->getReference(), md->getOutputFileBase(), md->anchor(),name);
- }
- else
- {
- t << convertToDocBook(name);
- }
- }
- index=newIndex+matchLen;
- }
- t << ldefLine.right(ldefLine.length()-index);
- t<< ".";
- t << "</para></formalpara>";
- }
-}
-static void generateInlineCode(FTextStream &t,const char *scopeName, Definition *def)
-{
- static bool inlineSources = Config_getBool(INLINE_SOURCES);
- //printf("Source Fragment %s: %d-%d bodyDef=%p\n",name().data(),
- // m_startBodyLine,m_endBodyLine,m_bodyDef);
- if (inlineSources && def->hasSources())
- {
- QCString codeFragment;
- int actualStart=def->getStartBodyLine(),actualEnd=def->getEndBodyLine();
- if (readCodeFragment(def->getBodyDef()->absFilePath(),
- actualStart,actualEnd,codeFragment)
- )
- {
- //printf("Adding code fragment '%s' ext='%s'\n",
- // codeFragment.data(),m_impl->defFileExt.data());
- ParserInterface *pIntf = Doxygen::parserManager->getParser(def->getDefFileExtension());
- pIntf->resetCodeParserState();
- //printf("Read:\n`%s'\n\n",codeFragment.data());
- MemberDef *thisMd = 0;
- if (def->definitionType()==Definition::TypeMember) thisMd = (MemberDef *)def;
-
- DocbookCodeGenerator *docbookGen = new DocbookCodeGenerator(t);
- docbookGen->startCodeFragment();
- pIntf->parseCode(*docbookGen, // codeOutIntf
- scopeName, // scope
- codeFragment, // input
- def->getLanguage(), // lang
- FALSE, // isExample
- 0, // exampleName
- def->getBodyDef(), // fileDef
- actualStart, // startLine
- actualEnd, // endLine
- TRUE, // inlineFragment
- thisMd, // memberDef
- TRUE // show line numbers
- );
- docbookGen->finish();
- docbookGen->endCodeFragment();
- delete docbookGen;
- }
- }
-}
-
-static void definedAtLine(int line, QCString fileName, FTextStream &t)
-{
- QCString refText = theTranslator->trDefinedAtLineInSourceFile();
- int lineMarkerPos = refText.find("@0");
- int fileMarkerPos = refText.find("@1");
- if (lineMarkerPos!=-1 && fileMarkerPos!=-1) // should always pass this.
- {
- if (lineMarkerPos<fileMarkerPos) // line marker before file marker
- {
- t << refText.left(lineMarkerPos)
- << line
- << refText.mid(lineMarkerPos+2, fileMarkerPos-lineMarkerPos-2)
- << fileName
- << refText.right(refText.length()-fileMarkerPos-2);
- }
- else // file marker before line marker
- {
- t << refText.left(fileMarkerPos)
- << fileName
- << refText.mid(fileMarkerPos+2, lineMarkerPos-fileMarkerPos-2)
- << line
- << refText.right(refText.length()-lineMarkerPos-2);
- }
- }
- else
- {
- err("translation error: invalid markers in trDefinedAtLineInSourceFile()\n");
- }
-}
-
-static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *def, bool detailed=0)
-{
- // + declaration/definition arg lists
- // + reimplements
- // + reimplementedBy
- // + exceptions
- // + const/volatile specifiers
- // - examples
- // + source definition
- // + source references
- // + source referenced by
- // - body code
- // + template arguments
- // (templateArguments(), definitionTemplateParameterLists())
- // - call graph
-
- // enum values are written as part of the enum
- if (md->memberType()==MemberType_EnumValue) return;
- if (md->isHidden()) return;
- //if (md->name().at(0)=='@') return; // anonymous member
-
- // group members are only visible in their group
- //if (def->definitionType()!=Definition::TypeGroup && md->getGroupDef()) return;
- QCString memType;
- switch (md->memberType())
- {
- case MemberType_Define: memType="define"; break;
- case MemberType_Function: memType="function"; break;
- case MemberType_Variable: memType="variable"; break;
- case MemberType_Typedef: memType="typedef"; break;
- case MemberType_Enumeration: memType="enum"; break;
- case MemberType_EnumValue: ASSERT(0); break;
- case MemberType_Signal: memType="signal"; break;
- case MemberType_Slot: memType="slot"; break;
- case MemberType_Friend: memType="friend"; break;
- case MemberType_DCOP: memType="dcop"; break;
- case MemberType_Property: memType="property"; break;
- case MemberType_Event: memType="event"; break;
- case MemberType_Interface: memType="interface"; break;
- case MemberType_Service: memType="service"; break;
- }
- QCString scopeName;
- if (md->getClassDef())
- {
- scopeName=md->getClassDef()->name();
- }
- else if (md->getNamespaceDef())
- {
- scopeName=md->getNamespaceDef()->name();
- }
- if (detailed==0)
- {
- t << " <para>" << endl;
- t << " <itemizedlist>" << endl;
- t << " <listitem>" << endl;
- //enum
- bool closePara=TRUE;
- if (md->memberType()==MemberType_Enumeration)
- {
- bool inLi[5]={ FALSE, FALSE, FALSE, FALSE, FALSE };
- MemberList *enumFields = md->enumFieldList();
- t << " <para><literallayout>" << memType << " <link linkend=\"_";
- if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
- {
- t << md->getGroupDef()->getOutputFileBase();
- }
- else
- {
- t << memberOutputFileBase(md);
- }
- t << "_1" << md->anchor() << "\">" << convertToDocBook(md->name()) << "</link>";
- if (enumFields!=0)
- {
- MemberListIterator emli(*enumFields);
- MemberDef *emd;
- t << " {" << endl;
- int cnt=0;
- for (emli.toFirst();(emd=emli.current());++emli)
- {
- if (cnt!=0)
- {
- t << "," << endl;
- }
- t << "<link linkend=\"_" << memberOutputFileBase(emd) << "_1" << emd->anchor() << "\">";
- writeDocbookString(t,emd->name());
- t << "</link>";
- if (!emd->initializer().isEmpty())
- {
- writeDocbookString(t,emd->initializer());
- }
- cnt++;
- }
- t << endl << "}";
- }
- t << "</literallayout>" << endl;
- if (md->briefDescription())
- {
- t << "<para><emphasis>";
- writeDocbookString(t,md->briefDescription());
- t << "</emphasis></para>" << endl;
- }
- }
- else if (md->memberType()==MemberType_Define)
- {
- t << " <para>" << "#" << memType << " <link linkend=\"_";
- if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
- {
- t << md->getGroupDef()->getOutputFileBase();
- }
- else
- {
- t << memberOutputFileBase(md);
- }
- t << "_1" << md->anchor() << "\">" << convertToDocBook(md->name()) << "</link>";
- if (!md->initializer().isEmpty() && md->initializer().length()<2000)
- {
- t << " ";
- linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,md->initializer());
- }
- if (md->briefDescription())
- {
- t << "<para><emphasis>";
- writeDocbookString(t,md->briefDescription());
- t << "</emphasis></para>" << endl;
- }
- }
- else if (md->memberType()==MemberType_Variable)
- {
- if (md->getClassDef())
- {
- t << " <para>" << convertToDocBook(md->declaration());
- if (md->briefDescription())
- {
- t << "<para><emphasis>";
- writeDocbookString(t,md->briefDescription());
- t << "</emphasis></para>";
- }
- }
- else
- {
- t << " <para>";
- linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,md->typeString());
- t << " <link linkend=\"_";
- if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
- {
- t << md->getGroupDef()->getOutputFileBase();
- }
- else
- {
- t << memberOutputFileBase(md);
- }
- t << "_1" << md->anchor() << "\">" << convertToDocBook(md->name()) << "</link>";
- if (md->briefDescription())
- {
- t << "<para><emphasis>";
- writeDocbookString(t,md->briefDescription());
- t << "</emphasis></para>" << endl;
- }
- }
- }
- else if (md->memberType()==MemberType_Typedef)
- {
- t << " <para>" << memType;
- t << " ";
- linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,md->typeString());
- t << " ";
- t << " <link linkend=\"_";
- if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
- {
- t << md->getGroupDef()->getOutputFileBase();
- }
- else
- {
- t << memberOutputFileBase(md);
- }
- t << "_1" << md->anchor() << "\">" << convertToDocBook(md->name()) << "</link>";
- if (md->briefDescription())
- {
- t << "<para><emphasis>";
- writeDocbookString(t,md->briefDescription());
- t << "</emphasis></para>" << endl;
- }
- }
- else if (md->memberType()==MemberType_Function)
- {
- t << " <para>";
- linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,md->typeString());
- t << " <link linkend=\"_";
- if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
- {
- t << md->getGroupDef()->getOutputFileBase();
- }
- else
- {
- t << memberOutputFileBase(md);
- }
- t << "_1" << md->anchor() << "\">" << convertToDocBook(md->name()) << "</link>";
- t << " (" << endl;
- ArgumentList *declAl = md->declArgumentList();
- if (declAl && declAl->count()>0)
- {
- ArgumentListIterator declAli(*declAl);
- Argument *a;
- int cnt=0;
- for (declAli.toFirst();(a=declAli.current());++declAli)
- {
- if (cnt!=0)
- {
- t << ", ";
- }
- if (!a->type.isEmpty())
- {
- linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,a->type);
- }
- t << " ";
- if (!a->name.isEmpty())
- {
- writeDocbookString(t,a->name);
- }
- cnt++;
- }
- }
- t << ")";
- if (md->briefDescription())
- {
- t << "<para><emphasis>";
- writeDocbookString(t,md->briefDescription());
- t << "</emphasis></para>" << endl;
- }
- }
- else
- {
- closePara = FALSE;
- }
- if (closePara) t << "</para>" << endl;
- t << " </listitem>" << endl;
- t << " </itemizedlist>" << endl;
- t << " </para>" << endl;
- }
- else
- {
- if (md->memberType()==MemberType_Enumeration)
- {
- MemberList *enumFields = md->enumFieldList();
- t << " <section xml:id=\"_";
- if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
- {
- t << md->getGroupDef()->getOutputFileBase();
- }
- else
- {
- t << memberOutputFileBase(md);
- }
- t << "_1" << md->anchor() << "\">" << endl;
- t << " <title>" << memType << " " << convertToDocBook(md->name()) << " " << "</title>" << endl;
- t << " ";
- writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
- t << endl;
- if (enumFields!=0)
- {
- MemberListIterator emli(*enumFields);
- MemberDef *emd;
- t << " <formalpara>" << endl;
- t << " <title>" << theTranslator->trEnumerationValues() << ":</title>" << endl;
- t << " <variablelist>" << endl;
- for (emli.toFirst();(emd=emli.current());++emli)
- {
- t << " <varlistentry xml:id=\"_";
- t << memberOutputFileBase(emd) << "_1" << emd->anchor() << "\">" << endl;
- t << " <term>";
- writeDocbookString(t,emd->name());
- t << "</term>" << endl;
- t << " <listitem>" << endl;
- if(Config_getBool(REPEAT_BRIEF))
- {
- t << " <para>";
- writeDocbookString(t,emd->briefDescription());
- t << "</para>" << endl;
- }
- t << " </listitem>" << endl;
- t << " </varlistentry>" << endl;
- }
- t << " </variablelist>" << endl;
- t << " </formalpara>" << endl;
- t << " <para>";
- t << " <para>";
- definedAtLine(md->getDefLine(),stripPath(md->getDefFileName()),t);
- t << "</para>" << endl;
-
- t << " <literallayout><computeroutput>" << endl;
- t << "{" << endl;
- for (emli.toFirst();(emd=emli.current());++emli)
- {
- writeDocbookString(t,emd->name());
- if (!emd->initializer().isEmpty())
- {
- writeDocbookString(t,emd->initializer());
- }
- t << ", " << endl;
- }
- t << "}" << convertToDocBook(md->name()) << ";" << endl;
- t << " </computeroutput></literallayout>" << endl;
- t << " </para>" << endl;
- }
- t << " </section>" << endl;
- }
- else if (md->memberType()==MemberType_Typedef)
- {
- t << " <section xml:id=\"_";
- if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
- {
- t << md->getGroupDef()->getOutputFileBase();
- }
- else
- {
- t << memberOutputFileBase(md);
- }
- t << "_1" << md->anchor() << "\">" << endl;
- t << " <title>" << convertToDocBook(md->definition()) << "</title>";
- if(Config_getBool(REPEAT_BRIEF))
- {
- t << " <emphasis>";
- writeDocbookString(t,md->briefDescription());
- t << "</emphasis>" << endl;
- }
- t << " ";
- writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
- t << endl;
- t << " </section>" << endl;
- }
- else if (md->memberType()==MemberType_Function)
- {
- t << " <section xml:id=\"_";
- if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
- {
- t << md->getGroupDef()->getOutputFileBase();
- }
- else
- {
- t << memberOutputFileBase(md);
- }
- t << "_1" << md->anchor() << "\">" << endl;
- t << " <title>" << convertToDocBook(md->definition()) << " " << convertToDocBook(md->argsString()) << "</title>";
- addIndexTerm(t,md->name(),def->name());
- addIndexTerm(t,def->name(),md->name());
- if(Config_getBool(REPEAT_BRIEF))
- {
- if (!md->briefDescription().isEmpty())
- {
- t << " <emphasis>";
- writeDocbookString(t,md->briefDescription());
- t << "</emphasis>" << endl;
- }
- }
- t << " ";
- writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
- t << endl;
-
- if (Config_getBool(REFERENCED_BY_RELATION))
- {
- generateSourceRefList(t,md->name(),theTranslator->trReferencedBy(),md->getReferencedByMembers(),md);
- }
- if (Config_getBool(REFERENCES_RELATION))
- {
- generateSourceRefList(t,md->name(),theTranslator->trReferences(),md->getReferencesMembers(),md);
- }
- generateInlineCode(t,md->name(),md);
- t << " </section>" << endl;
- }
- else if (md->memberType()==MemberType_Define)
- {
- if (md->documentation())
- {
- t << " <section xml:id=\"_";
- if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
- {
- t << md->getGroupDef()->getOutputFileBase();
- }
- else
- {
- t << memberOutputFileBase(md);
- }
- t << "_1" << md->anchor() << "\">" << endl;
- t << " <title>" << convertToDocBook(md->definition()) << "</title>";
- t << " ";
- writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
- t << endl;
- t << " </section>" << endl;
- }
- }
- else if (md->memberType()==MemberType_Variable)
- {
- if (md->getClassDef())
- {
- if (md->documentation())
- {
- t << " <section xml:id=\"_";
- if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
- {
- t << md->getGroupDef()->getOutputFileBase();
- }
- else
- {
- t << memberOutputFileBase(md);
- }
- t << "_1" << md->anchor() << "\">" << endl;
- t << " <title>" << convertToDocBook(md->definition()) << "</title>";
- addIndexTerm(t,md->name(),def->name());
- addIndexTerm(t,def->name(),md->name());
- t << " ";
- writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
- t << endl;
- t << " </section>" << endl;
- }
- }
- else
- {
- t << " <section xml:id=\"_";
- if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
- {
- t << md->getGroupDef()->getOutputFileBase();
- }
- else
- {
- t << memberOutputFileBase(md);
- }
- t << "_1" << md->anchor() << "\">" << endl;
- t << " <title>" << convertToDocBook(md->definition()) << "</title>";
- addIndexTerm(t,md->name(),def->name());
- addIndexTerm(t,def->name(),md->name());
- if(Config_getBool(REPEAT_BRIEF))
- {
- t << " <emphasis>";
- writeDocbookString(t,md->briefDescription());
- t << "</emphasis>" << endl;
- }
- t << " ";
- writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
- t << endl;
- t << " </section>" << endl;
- }
- }
- }
-}
-
-static void generateDocbookSection(Definition *d,FTextStream &t,MemberList *ml,const char *,
- bool detailed=0, const char *header=0,const char *documentation=0)
-{
- if (ml==0) return;
- MemberListIterator mli(*ml);
- MemberDef *md;
- int count=0;
- int doc_count=0;
- QCString title, desctitle, subtitle;
-
- for (mli.toFirst();(md=mli.current());++mli)
- {
- // namespace members are also inserted in the file scope, but
- // to prevent this duplication in the Docbook output, we filter those here.
- if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0)
- {
- count++;
- }
- }
-
- if (count==0) return; // empty list
-
- subtitle = "";
- switch (ml->listType())
- {
- case MemberListType_pubMethods: d->getLanguage()==SrcLangExt_ObjC ? title = theTranslator->trInstanceMethods() : title = theTranslator->trPublicMembers();
- switch (d->getLanguage())
- {
- case SrcLangExt_ObjC: desctitle = theTranslator->trMethodDocumentation(); break;
- case SrcLangExt_Fortran: desctitle = theTranslator->trMemberFunctionDocumentationFortran(); break;
- default: desctitle = theTranslator->trMemberFunctionDocumentation(); break;
- };
- break;
- case MemberListType_priMethods: title=theTranslator->trPrivateMembers(); desctitle=""; break;
-
- case MemberListType_decTypedefMembers: title=theTranslator->trTypedefs(); desctitle=theTranslator->trTypedefDocumentation(); break;
- case MemberListType_decEnumMembers: title=theTranslator->trEnumerations(); desctitle=theTranslator->trEnumerationTypeDocumentation(); break;
- case MemberListType_decFuncMembers: title=theTranslator->trFunctions(); desctitle=theTranslator->trFunctionDocumentation(); break;
- case MemberListType_decVarMembers: title=theTranslator->trVariables(); desctitle=theTranslator->trVariableDocumentation(); break;
- case MemberListType_pubAttribs: title=theTranslator->trPublicAttribs(); desctitle=theTranslator->trMemberDataDocumentation(); break;
- case MemberListType_priAttribs: title=theTranslator->trPrivateAttribs(); desctitle=theTranslator->trMemberDataDocumentation(); break;
- case MemberListType_proAttribs: title=theTranslator->trProtectedAttribs(); desctitle=theTranslator->trMemberDataDocumentation(); break;
- case MemberListType_decDefineMembers: title=theTranslator->trDefines(); desctitle=theTranslator->trDefineDocumentation(); break;
- case MemberListType_related: title=theTranslator->trRelatedFunctions(); desctitle=theTranslator->trRelatedFunctionDocumentation();
- subtitle=theTranslator->trRelatedSubscript(); break;
- default: title=""; desctitle="";
- }
-
- if (detailed)
- {
- for (mli.toFirst();(md=mli.current());++mli)
- {
- if (md->documentation().isEmpty() && !Config_getBool(REPEAT_BRIEF))
- {
- continue;
- }
- doc_count = 1;
- break;
- }
-
- if(doc_count == 0) return;
-
- if (!QCString(header).isEmpty())
- {
- t << " <section>" << endl;
- t << " <title>" << convertToDocBook(header) << "</title>" << endl;
- }
- else if (desctitle)
- {
- t << " <section>" << endl;
- t << " <title>" << desctitle << "</title>" << endl;
- }
- }
- else
- {
- t << " <section>" << endl;
- if (!QCString(header).isEmpty())
- {
- t << " <title>" << convertToDocBook(header) << "</title>" << endl;
- }
- else
- {
- t << " <title>" << title << "</title>" << endl;
- }
- if (!subtitle.isEmpty())
- t << " <para>" << subtitle << "</para>" << endl;
- }
-
- if (documentation)
- {
- t << " <description>";
- writeDocbookDocBlock(t,d->docFile(),d->docLine(),d,0,documentation);
- t << "</description>" << endl;
- }
- for (mli.toFirst();(md=mli.current());++mli)
- {
- // namespace members are also inserted in the file scope, but
- // to prevent this duplication in the Docbook output, we filter those here.
- if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0)
- {
- if (detailed && md->documentation().isEmpty() && !Config_getBool(REPEAT_BRIEF))
- {
- continue;
- }
-
- generateDocbookForMember(md,t,d,detailed);
- }
- }
- if (detailed)
- {
- if (!QCString(header).isEmpty())
- {
- t << " </section>" << endl;
- }
- else if (desctitle)
- {
- t << " </section>" << endl;
- }
- }
- else
- {
- t << " </section>" << endl;
- }
-}
-
-static void writeInnerClasses(const ClassSDict *cl,FTextStream &t)
-{
- if (cl)
- {
- ClassSDict::Iterator cli(*cl);
- ClassDef *cd;
- QCString title = theTranslator->trClasses();
-
- if (cli.toFirst())
- {
- t << " <section>" << endl;
- t << " <title> " << title << " </title>" << endl;
- }
- for (cli.toFirst();(cd=cli.current());++cli)
- {
- if (!cd->isHidden() && cd->name().find('@')==-1)
- {
- t << " <para>" << endl;
- t << " <itemizedlist>" << endl;
- t << " <listitem>" << endl;
- t << " <para>" << "struct <link linkend=\"_" << classOutputFileBase(cd) << "\">" << convertToDocBook(cd->name()) << "</link>";
- t << "</para>" << endl;
- if (cd->briefDescription())
- {
- t << "<para><emphasis>";
- writeDocbookString(t,cd->briefDescription());
- t << "</emphasis></para>" << endl;
- }
- t << " </listitem>" << endl;
- t << " </itemizedlist>" << endl;
- t << " </para>" << endl;
- }
- }
- if (cli.toFirst())
- {
- t << " </section>" << endl;
- }
- }
-}
-
-static void writeInnerNamespaces(const NamespaceSDict *nl,FTextStream &t)
-{
- if (nl)
- {
- NamespaceSDict::Iterator nli(*nl);
- NamespaceDef *nd;
- QCString title = theTranslator->trNamespaces();
-
- if (nli.toFirst())
- {
- t << " <simplesect>" << endl;
- t << " <title> " << title << " </title>" << endl;
- }
- for (nli.toFirst();(nd=nli.current());++nli)
- {
- if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymouse scopes
- {
- t << " <para>" << endl;
- t << " <itemizedlist>" << endl;
- t << " <listitem>" << endl;
- t << " <para>" << "struct <link linkend=\"_" << nd->getOutputFileBase() << "\">" << convertToDocBook(nd->name()) << "</link>";
- t << "</para>" << endl;
- t << " </listitem>" << endl;
- t << " </itemizedlist>" << endl;
- t << " </para>" << endl;
- }
- }
- if (nli.toFirst())
- {
- t << " </simplesect>" << endl;
- }
- }
-}
-
-static void writeInnerFiles(const FileList *fl,FTextStream &t)
-{
- if (fl)
- {
- QListIterator<FileDef> fli(*fl);
- FileDef *fd;
- QCString title = theTranslator->trFile(TRUE,TRUE);
-
- if (fli.toFirst())
- {
- t << " <simplesect>" << endl;
- t << " <title> " << title << " </title>" << endl;
- }
- for (fli.toFirst();(fd=fli.current());++fli)
- {
- t << " <para>" << endl;
- t << " <itemizedlist>" << endl;
- t << " <listitem>" << endl;
- t << " <para>" << "file <link linkend=\"_" << fd->getOutputFileBase() << "\">" << convertToDocBook(fd->name()) << "</link>";
- t << "</para>" << endl;
- t << " </listitem>" << endl;
- t << " </itemizedlist>" << endl;
- t << " </para>" << endl;
- }
- if (fli.toFirst())
- {
- t << " </simplesect>" << endl;
- }
- }
-}
-
-static void writeInnerPages(const PageSDict *pl,FTextStream &t)
-{
- if (pl)
- {
- PageSDict::Iterator pli(*pl);
- PageDef *pd;
-
- for (pli.toFirst();(pd=pli.current());++pli)
- {
- t << "<xi:include href=\"" << pd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
- }
- }
-}
-
-static void writeInnerGroups(const GroupList *gl,FTextStream &t)
-{
- if (gl)
- {
- GroupListIterator gli(*gl);
- GroupDef *sgd;
-
- //Docbook header tags for inner groups
- if (gli.toFirst())
- {
- t << " <simplesect>" << endl;
- t << " <title>" << theTranslator->trModules() << "</title>" << endl;
- t << " </simplesect>" << endl;
- t << " <para>" << endl;
- t << " <itemizedlist>" << endl;
- }
-
- for (gli.toFirst();(sgd=gli.current());++gli)
- {
- t << " <listitem><para><link linkend=\"_" << sgd->getOutputFileBase() << "\">" << convertToDocBook(sgd->groupTitle()) << "</link></para></listitem>" << endl;
- }
-
- //Docbook footer tags for inner groups
- if (gli.toFirst())
- {
- t << " </itemizedlist>" << endl;
- t << " </para>" << endl;
- }
-
- }
-}
-
-static void writeInnerDirs(const DirList *dl,FTextStream &t)
-{
- if (dl)
- {
- QListIterator<DirDef> subdirs(*dl);
- DirDef *subdir;
- QCString title = theTranslator->trDirectories();
- if (subdirs.toFirst())
- {
- t << " <simplesect>" << endl;
- t << " <title> " << title << " </title>" << endl;
- }
- for (subdirs.toFirst();(subdir=subdirs.current());++subdirs)
- {
- t << " <para>" << endl;
- t << " <itemizedlist>" << endl;
- t << " <listitem>" << endl;
- t << " <para>" << "dir <link linkend=\"_" << subdir->getOutputFileBase() << "\">" << convertToDocBook(subdir->displayName()) << "</link>";
- t << "</para>" << endl;
- t << " </listitem>" << endl;
- t << " </itemizedlist>" << endl;
- t << " </para>" << endl;
- }
- if (subdirs.toFirst())
- {
- t << " </simplesect>" << endl;
- }
- }
-}
-
-static void writeInnerGroupFiles(const GroupList *gl,FTextStream &t)
-{
- if (gl)
- {
- GroupListIterator gli(*gl);
- GroupDef *sgd;
-
- for (gli.toFirst();(sgd=gli.current());++gli)
- {
- t << "<xi:include href=\"" << sgd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
- }
- }
-}
-
-static void generateDocbookForClass(ClassDef *cd,FTextStream &ti)
-{
- // + brief description
- // + detailed description
- // + template argument list(s)
- // - include file
- // + member groups
- // + inheritance diagram
- // + list of direct super classes
- // + list of direct sub classes
- // + list of inner classes
- // + collaboration diagram
- // + list of all members
- // + user defined member sections
- // + standard member sections
- // + detailed member documentation
- // - examples using the class
-
- if (cd->isReference()) return; // skip external references.
- if (cd->isHidden()) return; // skip hidden classes.
- if (cd->name().find('@')!=-1) return; // skip anonymous compounds.
- if (cd->templateMaster()!=0) return; // skip generated template instances.
-
- msg("Generating Docbook output for class %s\n",cd->name().data());
-
- QCString fileDocbook=cd->getOutputFileBase()+".xml";
- //Add the file Documentation info to index file
- ti << " <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
-
- QCString outputDirectory = Config_getString(DOCBOOK_OUTPUT);
- QCString fileName=outputDirectory+"/"+ classOutputFileBase(cd)+".xml";
- QCString relPath = relativePathToRoot(fileName);
- QFile f(fileName);
- if (!f.open(IO_WriteOnly))
- {
- err("Cannot open file %s for writing!\n",fileName.data());
- return;
- }
- FTextStream t(&f);
- //t.setEncoding(FTextStream::UnicodeUTF8);
-
- writeDocbookHeader_ID(t, classOutputFileBase(cd));
- t << "<title>";
- writeDocbookString(t,cd->name());
- addIndexTerm(t,cd->name());
- t << " " << cd->compoundTypeString() << " Reference";
- t << "</title>" << endl;
- if (cd->briefDescription())
- {
- t << " <para>" << endl;
- writeDocbookDocBlock(t,cd->briefFile(),cd->briefLine(),cd,0,cd->briefDescription());
- t << " </para>" << endl;
- }
-
- IncludeInfo *ii=cd->includeInfo();
- if (ii)
- {
- QCString nm = ii->includeName;
- if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
- if (!nm.isEmpty())
- {
- t << "<para>" << endl;
- t << " <programlisting>#include ";
- if (ii->fileDef && !ii->fileDef->isReference()) // TODO: support external references
- {
- t << "<link linkend=\"_" << ii->fileDef->getOutputFileBase() << "\">";
- }
- if (ii->local)
- {
- t << "&quot;";
- }
- else
- {
- t << "&lt;";
- }
- t << convertToDocBook(nm);
- if (ii->local)
- {
- t << "&quot;";
- }
- else
- {
- t << "&gt;";
- }
- if (ii->fileDef && !ii->fileDef->isReference())
- {
- t << "</link>";
- }
- t << "</programlisting>" << endl;
- t << "</para>" << endl;
- }
- }
-
- if (Config_getBool(HAVE_DOT) && (Config_getBool(CLASS_DIAGRAMS) || Config_getBool(CLASS_GRAPH)))
- {
- t << "<para>Inheritance diagram for " << convertToDocBook(cd->name()) << "</para>" << endl;
- DotClassGraph inheritanceGraph(cd,DotNode::Inheritance);
- inheritanceGraph.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,TRUE,FALSE);
- }
-
- if (Config_getBool(HAVE_DOT) && Config_getBool(COLLABORATION_GRAPH))
- {
- t << "<para>Collaboration diagram for " << convertToDocBook(cd->name()) << "</para>" << endl;
- DotClassGraph collaborationGraph(cd,DotNode::Collaboration);
- collaborationGraph.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,TRUE,FALSE);
- }
-
- writeInnerClasses(cd->getClassSDict(),t);
-
- writeTemplateList(cd,t);
- if (cd->getMemberGroupSDict())
- {
- MemberGroupSDict::Iterator mgli(*cd->getMemberGroupSDict());
- MemberGroup *mg;
- for (;(mg=mgli.current());++mgli)
- {
- generateDocbookSection(cd,t,mg->members(),"user-defined",0,mg->header(),
- mg->documentation());
- }
- }
-
- QListIterator<MemberList> mli(cd->getMemberLists());
- MemberList *ml;
- for (mli.toFirst();(ml=mli.current());++mli)
- {
- if ((ml->listType()&MemberListType_detailedLists)==0)
- {
- generateDocbookSection(cd,t,ml,g_docbookSectionMapper.find(ml->listType()));
- }
- }
-
- if ((Config_getBool(REPEAT_BRIEF) && cd->briefDescription()) || cd->documentation())
- {
- t << " <simplesect>" << endl;
- t << " <title>" << theTranslator->trDetailedDescription() << "</title>" << endl;
-
- if(Config_getBool(REPEAT_BRIEF))
- {
- if (cd->briefDescription())
- {
- t << " <para>" << endl;
- // A title as 'Brief Description' may not be necessary.
- //t << " <title>" << theTranslator->trBriefDescription() << "</title>" << endl;
- writeDocbookDocBlock(t,cd->briefFile(),cd->briefLine(),cd,0,cd->briefDescription());
- t << " </para>" << endl;
- }
- }
-
- if (cd->documentation())
- {
- writeDocbookDocBlock(t,cd->docFile(),cd->docLine(),cd,0,cd->documentation());
- }
- t << " </simplesect>" << endl;
- }
-
- if (cd->getMemberGroupSDict())
- {
- MemberGroupSDict::Iterator mgli(*cd->getMemberGroupSDict());
- MemberGroup *mg;
- for (;(mg=mgli.current());++mgli)
- {
- generateDocbookSection(cd,t,mg->members(),"user-defined",1,mg->header(),
- mg->documentation());
- }
- }
-
- for (mli.toFirst();(ml=mli.current());++mli)
- {
- if ((ml->listType()&MemberListType_detailedLists)==0)
- {
- generateDocbookSection(cd,t,ml,g_docbookSectionMapper.find(ml->listType()),1);
- }
- }
-
- /*// TODO: Handling of Inheritance and Colloboration graph for Docbook to be implemented
- DotClassGraph inheritanceGraph(cd,DotNode::Inheritance);
- if (!inheritanceGraph.isTrivial())
- {
- t << " <inheritancegraph>" << endl;
- inheritanceGraph.writeDocbook(t);
- t << " </inheritancegraph>" << endl;
- }
- DotClassGraph collaborationGraph(cd,DotNode::Collaboration);
- if (!collaborationGraph.isTrivial())
- {
- t << " <collaborationgraph>" << endl;
- collaborationGraph.writeDocbook(t);
- t << " </collaborationgraph>" << endl;
- }
- t << " <location file=\""
- << cd->getDefFileName() << "\" line=\""
- << cd->getDefLine() << "\"";
- if (cd->getStartBodyLine()!=-1)
- {
- FileDef *bodyDef = cd->getBodyDef();
- if (bodyDef)
- {
- t << " bodyfile=\"" << bodyDef->absFilePath() << "\"";
- }
- t << " bodystart=\"" << cd->getStartBodyLine() << "\" bodyend=\""
- << cd->getEndBodyLine() << "\"";
- }
- t << "/>" << endl;
- writeListOfAllMembers(cd,t);
- */
-
- t << " <para>" << cd->generatedFromFiles() << "</para>" << endl;
- t << " <para><itemizedlist><listitem><para>" << stripPath(cd->getDefFileName()) << "</para></listitem></itemizedlist></para>" << endl;
- t << "</section>" << endl;
-
-}
-
-static void generateDocbookForNamespace(NamespaceDef *nd,FTextStream &ti)
-{
- // + contained class definitions
- // + contained namespace definitions
- // + member groups
- // + normal members
- // + brief desc
- // + detailed desc
- // + location
- // - files containing (parts of) the namespace definition
-
- if (nd->isReference() || nd->isHidden()) return; // skip external references
-
- QCString fileDocbook=nd->getOutputFileBase()+".xml";
- //Add the file Documentation info to index file
- ti << " <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
-
- QCString outputDirectory = Config_getString(DOCBOOK_OUTPUT);
- QCString fileName=outputDirectory+"/"+nd->getOutputFileBase()+".xml";
- QFile f(fileName);
- if (!f.open(IO_WriteOnly))
- {
- err("Cannot open file %s for writing!\n",fileName.data());
- return;
- }
- FTextStream t(&f);
- //t.setEncoding(FTextStream::UnicodeUTF8);
-
- writeDocbookHeader_ID(t, nd->getOutputFileBase());
- t << "<title>";
- addIndexTerm(t,nd->displayName());
- writeDocbookString(t,nd->title());
- t << "</title>" << endl;
-
- if (nd->briefDescription())
- {
- t << " <para>" << endl;
- //t << " <title>" << theTranslator->trBriefDescription() << "</title>" << endl;
- t << " </para>" << endl;
- }
- writeInnerClasses(nd->getClassSDict(),t);
- writeInnerNamespaces(nd->getNamespaceSDict(),t);
-
- if (nd->getMemberGroupSDict())
- {
- MemberGroupSDict::Iterator mgli(*nd->getMemberGroupSDict());
- MemberGroup *mg;
- for (;(mg=mgli.current());++mgli)
- {
- generateDocbookSection(nd,t,mg->members(),"user-defined",0,mg->header(),
- mg->documentation());
- }
- }
-
- QListIterator<MemberList> mli(nd->getMemberLists());
- MemberList *ml;
- for (mli.toFirst();(ml=mli.current());++mli)
- {
- if ((ml->listType()&MemberListType_declarationLists)!=0)
- {
- generateDocbookSection(nd,t,ml,g_docbookSectionMapper.find(ml->listType()));
- }
- }
-
- if ((Config_getBool(REPEAT_BRIEF) && nd->briefDescription()) || nd->documentation())
- {
- t << " <simplesect>" << endl;
- t << " <title>" << theTranslator->trDetailedDescription() << "</title>" << endl;
-
- if(Config_getBool(REPEAT_BRIEF))
- {
- if (nd->briefDescription())
- {
- t << " <para>" << endl;
- //t << " <title>" << theTranslator->trBriefDescription() << "</title>" << endl;
- writeDocbookDocBlock(t,nd->briefFile(),nd->briefLine(),nd,0,nd->briefDescription());
- t << " </para>" << endl;
- }
- }
-
- if (nd->documentation())
- {
- writeDocbookDocBlock(t,nd->docFile(),nd->docLine(),nd,0,nd->documentation());
- }
- t << " </simplesect>" << endl;
- }
-
- if (nd->getMemberGroupSDict())
- {
- MemberGroupSDict::Iterator mgli(*nd->getMemberGroupSDict());
- MemberGroup *mg;
- for (;(mg=mgli.current());++mgli)
- {
- generateDocbookSection(nd,t,mg->members(),"user-defined",1,mg->header(),
- mg->documentation());
- }
- }
-
- for (mli.toFirst();(ml=mli.current());++mli)
- {
- if ((ml->listType()&MemberListType_detailedLists)==0)
- {
- if (ml->listType() != MemberListType_allMembersList &&
- ml->listType() != MemberListType_docFuncMembers)
- generateDocbookSection(nd,t,ml,g_docbookSectionMapper.find(ml->listType()),1);
- }
- }
- // we actually need here "namespace"
- // t << " <para>" << theTranslator->trGeneratedFromFiles(ClassDef::Struct, FALSE) << "</para>" << endl;
- // t << " <para><itemizedlist><listitem><para>" << stripPath(nd->getDefFileName()) << "</para></listitem></itemizedlist></para>" << endl;
- t << "</section>" << endl;
-}
-
-static void generateDocbookForFile(FileDef *fd,FTextStream &ti)
-{
- // + includes files
- // + includedby files
- // + include graph
- // + included by graph
- // + contained class definitions
- // + contained namespace definitions
- // + member groups
- // + normal members
- // + brief desc
- // + detailed desc
- // + source code
- // + location
- // - number of lines
-
- if (fd->isReference()) return; // skip external references
-
- QCString fileDocbook=fd->getOutputFileBase()+".xml";
- //Add the file Documentation info to index file
- ti << " <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
-
- QCString outputDirectory = Config_getString(DOCBOOK_OUTPUT);
- QCString fileName=outputDirectory+"/"+fd->getOutputFileBase()+".xml";
- QCString relPath = relativePathToRoot(fileName);
-
- QFile f(fileName);
- if (!f.open(IO_WriteOnly))
- {
- err("Cannot open file %s for writing!\n",fileName.data());
- return;
- }
- FTextStream t(&f);
- //t.setEncoding(FTextStream::UnicodeUTF8);
- writeDocbookHeader_ID(t, fd->getOutputFileBase());
-
- t << " <title>";
- writeDocbookString(t,fd->name());
- t << " File Reference";
- t << "</title>" << endl;
-
- if (fd->briefDescription())
- {
- t << " <para>" << endl;
- writeDocbookDocBlock(t,fd->briefFile(),fd->briefLine(),fd,0,fd->briefDescription());
- t << " </para>" << endl;
- }
-
- IncludeInfo *inc;
-
- if (fd->includeFileList())
- {
- QListIterator<IncludeInfo> ili1(*fd->includeFileList());
- for (ili1.toFirst();(inc=ili1.current());++ili1)
- {
- t << " <programlisting>#include ";
- if (inc->local)
- {
- t << "&quot;";
- }
- else
- {
- t << "&lt;";
- }
- t << convertToDocBook(inc->includeName);
- if (inc->local)
- {
- t << "&quot;";
- }
- else
- {
- t << "&gt;";
- }
- t << "</programlisting>" << endl;
- }
- }
- if (Config_getBool(HAVE_DOT))
- {
- if (Config_getBool(INCLUDE_GRAPH))
- {
- t << "<para>Include dependency diagram for " << convertToDocBook(fd->name()) << "</para>" << endl;
- DotInclDepGraph idepGraph(fd, FALSE);
- idepGraph.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,FALSE);
- }
- if (Config_getBool(INCLUDED_BY_GRAPH))
- {
- t << "<para>Included by dependency diagram for " << convertToDocBook(fd->name()) << "</para>" << endl;
- DotInclDepGraph ibdepGraph(fd, TRUE);
- ibdepGraph.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,FALSE);
- }
- }
-
- if (fd->getClassSDict())
- {
- writeInnerClasses(fd->getClassSDict(),t);
- }
- if (fd->getNamespaceSDict())
- {
- writeInnerNamespaces(fd->getNamespaceSDict(),t);
- }
-
- if (fd->getMemberGroupSDict())
- {
- MemberGroupSDict::Iterator mgli(*fd->getMemberGroupSDict());
- MemberGroup *mg;
- for (;(mg=mgli.current());++mgli)
- {
- generateDocbookSection(fd,t,mg->members(),"user-defined",0,mg->header(),
- mg->documentation());
- }
- }
-
- QListIterator<MemberList> mli(fd->getMemberLists());
- MemberList *ml;
- for (mli.toFirst();(ml=mli.current());++mli)
- {
- if ((ml->listType()&MemberListType_declarationLists)!=0)
- {
- generateDocbookSection(fd,t,ml,g_docbookSectionMapper.find(ml->listType()));
- }
- }
-
- t << " <simplesect>" << endl;
- t << " <title>" << theTranslator->trDetailedDescription() << "</title>" << endl;
- if(Config_getBool(REPEAT_BRIEF))
- {
- if (fd->briefDescription())
- {
- writeDocbookDocBlock(t,fd->briefFile(),fd->briefLine(),fd,0,fd->briefDescription());
- }
- }
- writeDocbookDocBlock(t,fd->docFile(),fd->docLine(),fd,0,fd->documentation());
- if (Config_getBool(FULL_PATH_NAMES))
- {
- t << " <para>Definition in file " << fd->getDefFileName() << "</para>" << endl;
- }
- else
- {
- t << " <para>Definition in file " << stripPath(fd->getDefFileName()) << "</para>" << endl;
- }
- t << " </simplesect>" << endl;
-
- for (mli.toFirst();(ml=mli.current());++mli)
- {
- if ((ml->listType()&MemberListType_declarationLists)!=0)
- {
- generateDocbookSection(fd,t,ml,g_docbookSectionMapper.find(ml->listType()),1);
- }
- }
-
- if (Config_getBool(DOCBOOK_PROGRAMLISTING))
- {
- t << " <literallayout><computeroutput>" << endl;;
- writeDocbookCodeBlock(t,fd);
- t << " </computeroutput></literallayout>" << endl;
- }
-
- t << "</section>" << endl;
-}
-
-static void generateDocbookForGroup(GroupDef *gd,FTextStream &ti)
-{
- // + members
- // + member groups
- // + files
- // + classes
- // + namespaces
- // - packages
- // + pages
- // + child groups
- // - examples
- // + brief description
- // + detailed description
-
- if (gd->isReference()) return; // skip external references
-
- if (!gd->isASubGroup())
- {
- QCString fileDocbook=gd->getOutputFileBase()+".xml";
- //Add the file Documentation info to index file
- ti << " <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
- }
-
- QCString outputDirectory = Config_getString(DOCBOOK_OUTPUT);
- QCString fileName=outputDirectory+"/"+gd->getOutputFileBase()+".xml";
- QCString relPath = relativePathToRoot(fileName);
-
- QFile f(fileName);
- if (!f.open(IO_WriteOnly))
- {
- err("Cannot open file %s for writing!\n",fileName.data());
- return;
- }
-
- FTextStream t(&f);
- //t.setEncoding(FTextStream::UnicodeUTF8);
- writeDocbookHeader_ID(t, gd->getOutputFileBase());
-
- t << " <title>" << convertToDocBook(gd->groupTitle()) << "</title>" << endl;
- if (gd->briefDescription())
- {
- t << " <para>" << endl;
- writeDocbookDocBlock(t,gd->briefFile(),gd->briefLine(),gd,0,gd->briefDescription());
- t << " </para>" << endl;
- }
-
- if (Config_getBool(GROUP_GRAPHS) && Config_getBool(HAVE_DOT))
- {
- t << "<para>Collaboration diagram for " << convertToDocBook(gd->groupTitle()) << "</para>" << endl;
- DotGroupCollaboration collaborationGraph(gd);
- collaborationGraph.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,FALSE);
- }
-
- writeInnerFiles(gd->getFiles(),t);
- writeInnerClasses(gd->getClasses(),t);
- writeInnerNamespaces(gd->getNamespaces(),t);
- writeInnerPages(gd->getPages(),t);
- writeInnerGroups(gd->getSubGroups(),t);
-
- if (gd->getMemberGroupSDict())
- {
- MemberGroupSDict::Iterator mgli(*gd->getMemberGroupSDict());
- MemberGroup *mg;
- for (;(mg=mgli.current());++mgli)
- {
- generateDocbookSection(gd,t,mg->members(),"user-defined",0,mg->header(),
- mg->documentation());
- }
- }
-
- QListIterator<MemberList> mli(gd->getMemberLists());
- MemberList *ml;
- for (mli.toFirst();(ml=mli.current());++mli)
- {
- if ((ml->listType()&MemberListType_declarationLists)!=0)
- {
- generateDocbookSection(gd,t,ml,g_docbookSectionMapper.find(ml->listType()));
- }
- }
-
- if(Config_getBool(REPEAT_BRIEF))
- {
- if (gd->briefDescription())
- {
- //t << " <section>" << endl;
- //t << " <title>" << theTranslator->trBriefDescription() << "</title>" << endl;
- writeDocbookDocBlock(t,gd->briefFile(),gd->briefLine(),gd,0,gd->briefDescription());
- //t << " </section>" << endl;
- }
- }
-
- if (gd->documentation())
- {
- t << " <simplesect>" << endl;
- t << " <title>" << theTranslator->trDetailedDescription() << "</title>" << endl;
- writeDocbookDocBlock(t,gd->docFile(),gd->docLine(),gd,0,gd->documentation());
- t << " </simplesect>" << endl;
- }
-
- for (mli.toFirst();(ml=mli.current());++mli)
- {
- if ((ml->listType()&MemberListType_declarationLists)!=0)
- {
- generateDocbookSection(gd,t,ml,g_docbookSectionMapper.find(ml->listType()),1);
- }
- }
-
- writeInnerGroupFiles(gd->getSubGroups(),t);
-
- t << "</section>" << endl;
-
-}
-
-static void generateDocbookForDir(DirDef *dd,FTextStream &ti)
-{
- if (dd->isReference()) return; // skip external references
-
- QCString fileDocbook=dd->getOutputFileBase()+".xml";
- //Add the file Documentation info to index file
- ti << " <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
-
- QCString outputDirectory = Config_getString(DOCBOOK_OUTPUT);
- QCString fileName=outputDirectory+"/"+dd->getOutputFileBase()+".xml";
- QFile f(fileName);
- QCString relPath = relativePathToRoot(fileName);
-
- if (!f.open(IO_WriteOnly))
- {
- err("Cannot open file %s for writing!\n",fileName.data());
- return;
- }
-
- FTextStream t(&f);
- //t.setEncoding(FTextStream::UnicodeUTF8);
- writeDocbookHeader_ID(t, dd->getOutputFileBase());
-
- t << " <title>";
- t << theTranslator->trDirReference(dd->displayName());
- t << "</title>" << endl;
- if (dd->briefDescription())
- {
- writeDocbookDocBlock(t,dd->briefFile(),dd->briefLine(),dd,0,dd->briefDescription());
- }
- if (Config_getBool(DIRECTORY_GRAPH) && Config_getBool(HAVE_DOT))
- {
- t << "<para>Directory dependency diagram for " << convertToDocBook(dd->displayName()) << "</para>" << endl;
- DotDirDeps dirdepGraph(dd);
- dirdepGraph.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,FALSE);
- }
-
- writeInnerDirs(&dd->subDirs(),t);
- writeInnerFiles(dd->getFiles(),t);
-
- t << " <simplesect>" << endl;
- t << " <title>" << theTranslator->trDetailedDescription() << "</title>" << endl;
- if (dd->briefDescription())
- {
- t << " <para>" << endl;
- writeDocbookDocBlock(t,dd->briefFile(),dd->briefLine(),dd,0,dd->briefDescription());
- t << " </para>" << endl;
- }
- writeDocbookDocBlock(t,dd->docFile(),dd->docLine(),dd,0,dd->documentation());
- t << " <para>Directory location is " << dd->name() << "</para>" << endl;
- t << " </simplesect>" << endl;
-
- t << "</section>" << endl;
-}
-
-static void generateDocbookForPage(PageDef *pd,FTextStream &ti,bool isExample)
-{
- // + name
- // + title
- // + documentation
-
- if (pd->isReference()) return;
-
- QCString pageName = pd->getOutputFileBase();
- if (pd->getGroupDef())
- {
- pageName+=(QCString)"_"+pd->name();
- }
- if (pageName=="index")
- {
- pageName="mainpage"; // to prevent overwriting the generated index page.
- }
-
- QCString outputDirectory = Config_getString(DOCBOOK_OUTPUT);
- QCString fileName=outputDirectory+"/"+pageName+".xml";
- QFile f(fileName);
- if (!f.open(IO_WriteOnly))
- {
- err("Cannot open file %s for writing!\n",fileName.data());
- return;
- }
-
- FTextStream t(&f);
- //t.setEncoding(FTextStream::UnicodeUTF8);
-
- if(isExample)
- {
- QCString fileDocbook=pageName+".xml";
- ti << " <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
- }
-
- if (!pd->hasParentPage() && !isExample)
- {
- QCString fileDocbook=pageName+".xml";
- //Add the file Documentation info to index file
- ti << " <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
- writeDocbookHeaderMainpage(t,pageName);
- }
- else
- {
- QCString pid;
- if(isExample)
- {
- pid = pageName;
- }
- else
- {
- pid = pageName+"_1"+pageName;
- }
- writeDocbookHeader_ID(t, pid);
- }
-
- SectionInfo *si = Doxygen::sectionDict->find(pd->name());
- if (si)
- {
- if ( pageName == "mainpage")
- t << " <title>" << convertToDocBook(theTranslator->trMainPage()) << "</title>" << endl;
- else
- t << " <title>" << convertToDocBook(si->title) << "</title>" << endl;
- }
- else
- {
- t << " <title>" << convertToDocBook(pd->name()) << "</title>" << endl;
- }
-
- generateTOC(t, pd);
- if (isExample)
- {
- writeDocbookDocBlock(t,pd->docFile(),pd->docLine(),pd,0,
- pd->documentation()+"\n\\include "+pd->name());
- }
- else
- {
- writeDocbookDocBlock(t,pd->docFile(),pd->docLine(),pd,0,
- pd->documentation());
- }
- writeInnerPages(pd->getSubPages(),t);
-
- if (!pd->hasParentPage() && !isExample)
- {
- t << endl << "</chapter>" << endl;
- }
- else
- {
- t << endl << "</section>" << endl;
- }
-}
-void generateDocbook_v1()
-{
-
- // + classes
- // + namespaces
- // + files
- // + groups
- // + related pages
- // - examples
-
- QCString outputDirectory = Config_getString(DOCBOOK_OUTPUT);
- if (outputDirectory.isEmpty())
- {
- outputDirectory=QDir::currentDirPath().utf8();
- }
- else
- {
- QDir dir(outputDirectory);
- if (!dir.exists())
- {
- dir.setPath(QDir::currentDirPath());
- if (!dir.mkdir(outputDirectory))
- {
- err("tag DOCBOOK_OUTPUT: Output directory `%s' does not "
- "exist and cannot be created\n",outputDirectory.data());
- exit(1);
- }
- else
- {
- msg("Notice: Output directory `%s' does not exist. "
- "I have created it for you.\n", outputDirectory.data());
- }
- dir.cd(outputDirectory);
- }
- outputDirectory=dir.absPath().utf8();
- }
-
- QDir dir(outputDirectory);
- if (!dir.exists())
- {
- dir.setPath(QDir::currentDirPath());
- if (!dir.mkdir(outputDirectory))
- {
- err("Cannot create directory %s\n",outputDirectory.data());
- return;
- }
- }
- QDir docbookDir(outputDirectory);
- createSubDirs(docbookDir);
-
- QCString fileName=outputDirectory+"/index.xml";
- QCString dbk_projectName = Config_getString(PROJECT_NAME);
- QFile f(fileName);
-
- f.setName(fileName);
- if (!f.open(IO_WriteOnly))
- {
- err("Cannot open file %s for writing!\n",fileName.data());
- return;
- }
- FTextStream t(&f);
- //t.setEncoding(FTextStream::UnicodeUTF8);
-
- // write index header for Docbook which calls the structure file
- t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;;
- t << "<book xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">" << endl;
- t << " <info>" << endl;
- t << " <title>" << convertToDocBook(dbk_projectName) << "</title>" << endl;
- t << " </info>" << endl;
-
- // NAMESPACE DOCUMENTATION
- NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
- NamespaceDef *nd;
-
- //Namespace Documentation index header
- if (nli.toFirst())
- {
- t << " <chapter>" << endl;
- t << " <title>Namespace Documentation</title>" << endl;
- }
-
- for (nli.toFirst();(nd=nli.current());++nli)
- {
- msg("Generating Docbook output for namespace %s\n",nd->name().data());
- generateDocbookForNamespace(nd,t);
- }
-
- //Namespace Documentation index footer
- if (nli.toFirst())
- {
- t << " </chapter>" << endl;
- }
-
- /** MAINPAGE DOCUMENTATION **/
-
- if (Doxygen::mainPage)
- {
- msg("Generating Docbook output for the main page\n");
- generateDocbookForPage(Doxygen::mainPage,t,FALSE);
- }
-
- // PAGE DOCUMENTATION
- {
- PageSDict::Iterator pdi(*Doxygen::pageSDict);
- PageDef *pd=0;
-
- for (pdi.toFirst();(pd=pdi.current());++pdi)
- {
- msg("Generating Docbook output for page %s\n",pd->name().data());
- generateDocbookForPage(pd,t,FALSE);
- }
- }
-
- /** MODULE GROUP DOCUMENTATION **/
-
- GroupSDict::Iterator gli(*Doxygen::groupSDict);
- GroupDef *gd;
-
- //Module group Documentation index header
- if (gli.toFirst())
- {
- t << " <chapter>" << endl;
- t << " <title>" << theTranslator->trModuleDocumentation() << "</title>" << endl;
- }
-
- for (;(gd=gli.current());++gli)
- {
- msg("Generating Docbook output for group %s\n",gd->name().data());
- generateDocbookForGroup(gd,t);
- }
-
- //Module group Documentation index footer
- if (gli.toFirst())
- {
- t << " </chapter>" << endl;
- }
-
- //CLASS DOCUMENTATION
-
- {
- ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd;
-
- //Class Documentation index header
- if (cli.toFirst())
- {
- t << " <chapter>" << endl;
- t << " <title>" << theTranslator->trClassDocumentation() << "</title>" << endl;
- }
-
- for (cli.toFirst();(cd=cli.current());++cli)
- {
- generateDocbookForClass(cd,t);
- }
-
- //Class Documentation index footer
- if (cli.toFirst())
- {
- t << " </chapter>" << endl;
- }
- }
-
- // FILE DOCUMENTATION
-
- static bool showFiles = Config_getBool(SHOW_FILES);
- if (showFiles)
- {
- FileNameListIterator fnli(*Doxygen::inputNameList);
- FileName *fn;
-
- //File Documentation index header
- if (fnli.toFirst())
- {
- t << " <chapter>" << endl;
- t << " <title>" << theTranslator->trFileDocumentation() << "</title>" << endl;
- }
-
- for (;(fn=fnli.current());++fnli)
- {
- FileNameIterator fni(*fn);
- FileDef *fd;
- for (;(fd=fni.current());++fni)
- {
- msg("Generating Docbook output for file %s\n",fd->name().data());
- generateDocbookForFile(fd,t);
- }
- }
-
- //File Documentation index footer
- if (fnli.toFirst())
- {
- t << " </chapter>" << endl;
- }
- }
-
- // DIRECTORY DOCUMENTATION
- if (Config_getBool(DIRECTORY_GRAPH) && Config_getBool(HAVE_DOT))
- {
- DirDef *dir;
- DirSDict::Iterator sdi(*Doxygen::directories);
-
- //Directory Documentation index header
- if (sdi.toFirst())
- {
- t << " <chapter>" << endl;
- t << " <title>" << theTranslator->trDirDocumentation() << "</title>" << endl;
- }
-
- for (sdi.toFirst();(dir=sdi.current());++sdi)
- {
- msg("Generate Docbook output for dir %s\n",dir->name().data());
- generateDocbookForDir(dir,t);
- }
-
- //Module group Documentation index footer
- if (sdi.toFirst())
- {
- t << " </chapter>" << endl;
- }
- }
-
- // EXAMPLE PAGE DOCUMENTATION
-
- {
- PageSDict::Iterator pdi(*Doxygen::exampleSDict);
- PageDef *pd=0;
-
- //Example Page Documentation index header
- if (pdi.toFirst())
- {
- t << " <chapter>" << endl;
- t << " <title>" << theTranslator->trExampleDocumentation() << "</title>" << endl;
- }
-
- for (pdi.toFirst();(pd=pdi.current());++pdi)
- {
- msg("Generating Docbook output for example %s\n",pd->name().data());
- generateDocbookForPage(pd,t,TRUE);
- }
-
- //Example Page Documentation index footer
- if (pdi.toFirst())
- {
- t << " </chapter>" << endl;
- }
- }
-
- t << "<index/>" << endl;
- t << "</book>" << endl;
-
-}
-
DocbookGenerator::DocbookGenerator() : OutputGenerator()
{
DB_GEN_C
@@ -2406,6 +259,13 @@ DB_GEN_C
//m_indent=0;
//templateMemberItem = FALSE;
m_prettyCode=Config_getBool(DOCBOOK_PROGRAMLISTING);
+ m_denseText = FALSE;
+ m_inGroup = FALSE;
+ m_inDetail = FALSE;
+ m_levelListItem = 0;
+ m_descTable = FALSE;
+ m_inLevel = -1;
+ m_firstMember = FALSE;
for (int i = 0 ; i < sizeof(m_inListItem) / sizeof(*m_inListItem) ; i++) m_inListItem[i] = FALSE;
for (int i = 0 ; i < sizeof(m_inSimpleSect) / sizeof(*m_inSimpleSect) ; i++) m_inSimpleSect[i] = FALSE;
}
@@ -2681,7 +541,7 @@ DB_GEN_C2("IndexSections " << is)
bool found=FALSE;
for (cli.toFirst();(cd=cli.current()) && !found;++cli)
{
- if (cd->isLinkableInProject() &&
+ if (cd->isLinkableInProject() &&
cd->templateMaster()==0 &&
!cd->isEmbeddedInOuterScope()
)
@@ -2692,13 +552,13 @@ DB_GEN_C2("IndexSections " << is)
}
for (;(cd=cli.current());++cli)
{
- if (cd->isLinkableInProject() &&
+ if (cd->isLinkableInProject() &&
cd->templateMaster()==0 &&
!cd->isEmbeddedInOuterScope()
)
{
t << " <xi:include href=\"" << cd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
- }
+ }
}
}
t << "</chapter>\n";
@@ -2707,7 +567,7 @@ DB_GEN_C2("IndexSections " << is)
{
t << "</title>" << endl;
bool isFirst=TRUE;
- FileNameListIterator fnli(*Doxygen::inputNameList);
+ FileNameListIterator fnli(*Doxygen::inputNameList);
FileName *fn;
for (fnli.toFirst();(fn=fnli.current());++fnli)
{
@@ -2885,7 +745,7 @@ void DocbookGenerator::startGroupHeader(int extraIndentLevel)
{
DB_GEN_C2("m_inLevel " << m_inLevel)
DB_GEN_C2("extraIndentLevel " << extraIndentLevel)
- m_firstMember = TRUE;
+ m_firstMember = TRUE;
if (m_inSimpleSect[m_levelListItem]) t << "</simplesect>" << endl;
m_inSimpleSect[m_levelListItem] = FALSE;
if (m_inLevel != -1) m_inGroup = TRUE;
@@ -3044,9 +904,15 @@ DB_GEN_C
void DocbookGenerator::endClassDiagram(const ClassDiagram &d, const char *fileName,const char *)
{
DB_GEN_C
- visitPreStart(t, FALSE, relPath + fileName + ".png", NULL, NULL);
+ t << " <informalfigure>" << endl;
+ t << " <mediaobject>" << endl;
+ t << " <imageobject>" << endl;
+ t << " <imagedata width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\""
+ << relPath << fileName << ".png\">" << "</imagedata>" << endl;
+ t << " </imageobject>" << endl;
d.writeImage(t,dir,relPath,fileName,FALSE);
- visitPostEnd(t, FALSE);
+ t << " </mediaobject>" << endl;
+ t << " </informalfigure>" << endl;
t << "</para>" << endl;
}
void DocbookGenerator::startLabels()
diff --git a/src/docbookgen.h b/src/docbookgen.h
index 3fafff1..08255a1 100644
--- a/src/docbookgen.h
+++ b/src/docbookgen.h
@@ -17,8 +17,6 @@
#include "outputgen.h"
-void generateDocbook_v1();
-
class DocbookCodeGenerator : public CodeOutputInterface
{
public:
@@ -350,16 +348,16 @@ private:
QCString relPath;
DocbookCodeGenerator m_codeGen;
- bool m_prettyCode = FALSE;
- bool m_denseText = FALSE;
- bool m_inGroup = FALSE;
- bool m_inDetail = FALSE;
- int m_levelListItem = 0;
+ bool m_prettyCode;
+ bool m_denseText;
+ bool m_inGroup;
+ bool m_inDetail;
+ int m_levelListItem;
bool m_inListItem[20];
bool m_inSimpleSect[20];
- bool m_descTable = FALSE;
- int m_inLevel = -1;
- bool m_firstMember = FALSE;
+ bool m_descTable;
+ int m_inLevel;
+ bool m_firstMember;
};
#endif
diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp
index da84931..f7fb10f 100644
--- a/src/docbookvisitor.cpp
+++ b/src/docbookvisitor.cpp
@@ -34,6 +34,7 @@
#include "msc.h"
#include "dia.h"
#include "htmlentity.h"
+#include "emoji.h"
#include "plantuml.h"
#if 0
@@ -47,12 +48,28 @@
#define DB_VIS_C2(y)
#define DB_VIS_C2a(x,y)
#endif
-void visitPreStart(FTextStream &t, const bool hasCaption, QCString name, QCString width, QCString height)
+
+void DocbookDocVisitor::visitCaption(const QList<DocNode> &children)
{
- QCString tmpStr;
- if (hasCaption)
+ QListIterator<DocNode> cli(children);
+ DocNode *n;
+ for (cli.toFirst();(n=cli.current());++cli) n->accept(this);
+}
+
+void DocbookDocVisitor::visitPreStart(FTextStream &t,
+ const QList<DocNode> &children,
+ bool hasCaption,
+ const QCString &name,
+ const QCString &width,
+ const QCString &height,
+ bool inlineImage)
+{
+ if (hasCaption && !inlineImage)
{
t << " <figure>" << endl;
+ t << " <title>" << endl;
+ visitCaption(children);
+ t << " </title>" << endl;
}
else
{
@@ -67,30 +84,30 @@ void visitPreStart(FTextStream &t, const bool hasCaption, QCString name, QCStri
}
else
{
- t << " width=\"50%\"";
+ if (!height.isEmpty() && !inlineImage) t << " width=\"50%\"";
}
if (!height.isEmpty())
{
- t << " depth=\"" << convertToDocBook(tmpStr) << "\"";
+ t << " depth=\"" << convertToDocBook(height) << "\"";
}
t << " align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << name << "\">";
t << "</imagedata>" << endl;
t << " </imageobject>" << endl;
- if (hasCaption)
+ if (hasCaption && !inlineImage)
{
- t << " <title>" << endl;
+ t << " <!--" << endl; // Needed for general formatting with title for other formats
}
}
-void visitPostEnd(FTextStream &t, const bool hasCaption)
+void DocbookDocVisitor::visitPostEnd(FTextStream &t, bool hasCaption, bool inlineImage)
{
t << endl;
- if (hasCaption)
+ if (hasCaption && !inlineImage)
{
- t << " </title>" << endl;
+ t << " -->" << endl; // Needed for general formatting with title for other formats
}
t << " </mediaobject>" << endl;
- if (hasCaption)
+ if (hasCaption && !inlineImage)
{
t << " </figure>" << endl;
}
@@ -100,13 +117,6 @@ void visitPostEnd(FTextStream &t, const bool hasCaption)
}
}
-static void visitCaption(DocbookDocVisitor *parent, QList<DocNode> children)
-{
- QListIterator<DocNode> cli(children);
- DocNode *n;
- for (cli.toFirst();(n=cli.current());++cli) n->accept(parent);
-}
-
DocbookDocVisitor::DocbookDocVisitor(FTextStream &t,CodeOutputInterface &ci)
: DocVisitor(DocVisitor_Docbook), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE)
{
@@ -168,6 +178,21 @@ DB_VIS_C
}
}
+void DocbookDocVisitor::visit(DocEmoji *s)
+{
+DB_VIS_C
+ if (m_hide) return;
+ const char *res = EmojiEntityMapper::instance()->docbook(s->emoji());
+ if (res)
+ {
+ m_t << res;
+ }
+ else
+ {
+ err("DocBook: non supported Emoji-entity found: %s\n",EmojiEntityMapper::instance()->html(s->emoji()));
+ }
+}
+
void DocbookDocVisitor::visit(DocURL *u)
{
DB_VIS_C
@@ -941,7 +966,8 @@ void DocbookDocVisitor::visitPost(DocHtmlTable *)
{
DB_VIS_C
if (m_hide) return;
- m_t << " </tbody>" << endl;
+ if (bodySet) m_t << " </tbody>" << endl;
+ bodySet = FALSE;
m_t << " </tgroup>" << endl;
m_t << "</informaltable>" << endl;
}
@@ -1147,7 +1173,7 @@ DB_VIS_C
{
baseName=baseName.right(baseName.length()-i-1);
}
- visitPreStart(m_t, img -> hasCaption(), img->relPath() + baseName, img -> width(), img -> height());
+ visitPreStart(m_t, img->children(), img->hasCaption(), img->relPath() + baseName, img->width(), img->height(), img->isInlineImage());
}
else
{
@@ -1162,7 +1188,7 @@ DB_VIS_C
if (img->type()==DocImage::DocBook)
{
if (m_hide) return;
- visitPostEnd(m_t, img -> hasCaption());
+ visitPostEnd(m_t, img -> hasCaption(),img -> isInlineImage());
// copy the image to the output dir
QCString baseName=img->name();
int i;
@@ -1201,7 +1227,7 @@ void DocbookDocVisitor::visitPre(DocDotFile *df)
{
DB_VIS_C
if (m_hide) return;
- startDotFile(df->file(),df->width(),df->height(),df->hasCaption());
+ startDotFile(df->file(),df->width(),df->height(),df->hasCaption(),df->children());
}
void DocbookDocVisitor::visitPost(DocDotFile *df)
@@ -1215,7 +1241,7 @@ void DocbookDocVisitor::visitPre(DocMscFile *df)
{
DB_VIS_C
if (m_hide) return;
- startMscFile(df->file(),df->width(),df->height(),df->hasCaption());
+ startMscFile(df->file(),df->width(),df->height(),df->hasCaption(),df->children());
}
void DocbookDocVisitor::visitPost(DocMscFile *df)
@@ -1228,7 +1254,7 @@ void DocbookDocVisitor::visitPre(DocDiaFile *df)
{
DB_VIS_C
if (m_hide) return;
- startDiaFile(df->file(),df->width(),df->height(),df->hasCaption());
+ startDiaFile(df->file(),df->width(),df->height(),df->hasCaption(),df->children());
}
void DocbookDocVisitor::visitPost(DocDiaFile *df)
@@ -1601,8 +1627,8 @@ DB_VIS_C
}
QCString outDir = Config_getString(DOCBOOK_OUTPUT);
writeMscGraphFromFile(baseName+".msc",outDir,shortName,MSC_BITMAP);
- visitPreStart(m_t, s->hasCaption(), s->relPath() + shortName + ".png", s->width(),s->height());
- visitCaption(this, s->children());
+ visitPreStart(m_t, s->children(), s->hasCaption(), s->relPath() + shortName + ".png", s->width(), s->height());
+ visitCaption(s->children());
visitPostEnd(m_t, s->hasCaption());
}
@@ -1617,15 +1643,16 @@ DB_VIS_C
}
QCString outDir = Config_getString(DOCBOOK_OUTPUT);
generatePlantUMLOutput(baseName,outDir,PUML_BITMAP);
- visitPreStart(m_t, s->hasCaption(), s->relPath() + shortName + ".png", s->width(),s->height());
- visitCaption(this, s->children());
+ visitPreStart(m_t, s->children(), s->hasCaption(), s->relPath() + shortName + ".png", s->width(),s->height());
+ visitCaption(s->children());
visitPostEnd(m_t, s->hasCaption());
}
void DocbookDocVisitor::startMscFile(const QCString &fileName,
const QCString &width,
const QCString &height,
- bool hasCaption
+ bool hasCaption,
+ const QList<DocNode> &children
)
{
DB_VIS_C
@@ -1643,7 +1670,7 @@ DB_VIS_C
QCString outDir = Config_getString(DOCBOOK_OUTPUT);
writeMscGraphFromFile(fileName,outDir,baseName,MSC_BITMAP);
m_t << "<para>" << endl;
- visitPreStart(m_t, hasCaption, baseName + ".png", width, height);
+ visitPreStart(m_t, children, hasCaption, baseName + ".png", width, height);
}
void DocbookDocVisitor::endMscFile(bool hasCaption)
@@ -1665,15 +1692,16 @@ DB_VIS_C
}
QCString outDir = Config_getString(DOCBOOK_OUTPUT);
writeDiaGraphFromFile(baseName+".dia",outDir,shortName,DIA_BITMAP);
- visitPreStart(m_t, s->hasCaption(), shortName, s->width(),s->height());
- visitCaption(this, s->children());
+ visitPreStart(m_t, s->children(), s->hasCaption(), shortName, s->width(),s->height());
+ visitCaption(s->children());
visitPostEnd(m_t, s->hasCaption());
}
void DocbookDocVisitor::startDiaFile(const QCString &fileName,
const QCString &width,
const QCString &height,
- bool hasCaption
+ bool hasCaption,
+ const QList<DocNode> &children
)
{
DB_VIS_C
@@ -1691,7 +1719,7 @@ DB_VIS_C
QCString outDir = Config_getString(DOCBOOK_OUTPUT);
writeDiaGraphFromFile(fileName,outDir,baseName,DIA_BITMAP);
m_t << "<para>" << endl;
- visitPreStart(m_t, hasCaption, baseName + ".png", width, height);
+ visitPreStart(m_t, children, hasCaption, baseName + ".png", width, height);
}
void DocbookDocVisitor::endDiaFile(bool hasCaption)
@@ -1713,15 +1741,16 @@ DB_VIS_C
}
QCString outDir = Config_getString(DOCBOOK_OUTPUT);
writeDotGraphFromFile(baseName+".dot",outDir,shortName,GOF_BITMAP);
- visitPreStart(m_t, s->hasCaption(), s->relPath() + shortName + "." + getDotImageExtension(), s->width(),s->height());
- visitCaption(this, s->children());
+ visitPreStart(m_t, s->children(), s->hasCaption(), s->relPath() + shortName + "." + getDotImageExtension(), s->width(),s->height());
+ visitCaption(s->children());
visitPostEnd(m_t, s->hasCaption());
}
void DocbookDocVisitor::startDotFile(const QCString &fileName,
const QCString &width,
const QCString &height,
- bool hasCaption
+ bool hasCaption,
+ const QList<DocNode> &children
)
{
DB_VIS_C
@@ -1740,7 +1769,7 @@ DB_VIS_C
QCString imgExt = getDotImageExtension();
writeDotGraphFromFile(fileName,outDir,baseName,GOF_BITMAP);
m_t << "<para>" << endl;
- visitPreStart(m_t, hasCaption, baseName + "." + imgExt, width, height);
+ visitPreStart(m_t, children, hasCaption, baseName + "." + imgExt, width, height);
}
void DocbookDocVisitor::endDotFile(bool hasCaption)
diff --git a/src/docbookvisitor.h b/src/docbookvisitor.h
index 40f8a68..24b1fbb 100644
--- a/src/docbookvisitor.h
+++ b/src/docbookvisitor.h
@@ -20,15 +20,14 @@
#include "docvisitor.h"
#include <qstack.h>
+#include <qlist.h>
#include <qcstring.h>
+#include <docparser.h>
class FTextStream;
class CodeOutputInterface;
class QCString;
-void visitPreStart(FTextStream &t, const bool hasCaption, QCString name, QCString width, QCString height);
-void visitPostEnd(FTextStream &t, const bool hasCaption);
-
/*! @brief Concrete visitor implementation for Docbook output. */
class DocbookDocVisitor : public DocVisitor
{
@@ -42,6 +41,7 @@ class DocbookDocVisitor : public DocVisitor
void visit(DocLinkedWord *);
void visit(DocWhiteSpace *);
void visit(DocSymbol *);
+ void visit(DocEmoji *);
void visit(DocURL *);
void visit(DocLineBreak *);
void visit(DocHorRuler *);
@@ -149,18 +149,27 @@ class DocbookDocVisitor : public DocVisitor
void pushEnabled();
void popEnabled();
void startMscFile(const QCString &fileName,const QCString &width,
- const QCString &height, bool hasCaption);
+ const QCString &height, bool hasCaption,const QList<DocNode> &children);
void endMscFile(bool hasCaption);
void writeMscFile(const QCString &fileName, DocVerbatim *s);
void startDiaFile(const QCString &fileName,const QCString &width,
- const QCString &height, bool hasCaption);
+ const QCString &height, bool hasCaption,const QList<DocNode> &children);
void endDiaFile(bool hasCaption);
void writeDiaFile(const QCString &fileName, DocVerbatim *s);
void startDotFile(const QCString &fileName,const QCString &width,
- const QCString &height, bool hasCaption);
+ const QCString &height, bool hasCaption,const QList<DocNode> &children);
void endDotFile(bool hasCaption);
void writeDotFile(const QCString &fileName, DocVerbatim *s);
void writePlantUMLFile(const QCString &fileName, DocVerbatim *s);
+ void visitPreStart(FTextStream &t,
+ const QList<DocNode> &children,
+ bool hasCaption,
+ const QCString &name,
+ const QCString &width,
+ const QCString &height,
+ bool inlineImage = FALSE);
+ void visitPostEnd(FTextStream &t, bool hasCaption, bool inlineImage = FALSE);
+ void visitCaption(const QList<DocNode> &children);
//--------------------------------------
// state variables
//--------------------------------------
diff --git a/src/docparser.cpp b/src/docparser.cpp
index b39b80e..f20c22d 100644
--- a/src/docparser.cpp
+++ b/src/docparser.cpp
@@ -55,6 +55,9 @@
#include "growbuf.h"
#include "markdown.h"
#include "htmlentity.h"
+#include "emoji.h"
+
+#define TK_COMMAND_CHAR(token) ((token)==TK_COMMAND_AT ? '@' : '\\')
// debug off
#define DBG(x) do {} while(0)
@@ -266,7 +269,7 @@ static void unescapeCRef(QCString &s)
* copies the image to the output directory (which depends on the \a type
* parameter).
*/
-static QCString findAndCopyImage(const char *fileName,DocImage::Type type)
+static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool dowarn = true)
{
QCString result;
bool ambig;
@@ -334,7 +337,8 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type)
}
else
{
- printf("Source & Destination are the same!\n");
+ warn(g_fileName,doctokenizerYYlineno,
+ "Prevented to copy file %s onto itself!\n",qPrint(inputFile));
}
}
else
@@ -362,7 +366,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type)
return baseName;
}
}
- else if (ambig)
+ else if (ambig && dowarn)
{
QCString text;
text.sprintf("image file name %s is ambiguous.\n",qPrint(fileName));
@@ -373,7 +377,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type)
else
{
result=fileName;
- if (result.left(5)!="http:" && result.left(6)!="https:")
+ if (result.left(5)!="http:" && result.left(6)!="https:" && dowarn)
{
warn_doc_error(g_fileName,doctokenizerYYlineno,
"image file %s is not found in IMAGE_PATH: "
@@ -866,7 +870,35 @@ static bool findDocsForMemberOrCompound(const char *commandName,
return FALSE;
}
//---------------------------------------------------------------------------
+inline void errorHandleDefaultToken(DocNode *parent,int tok,
+ QList<DocNode> &children,const char *txt)
+{
+ switch (tok)
+ {
+ case TK_COMMAND_AT:
+ // fall through
+ case TK_COMMAND_BS:
+ children.append(new DocWord(parent,TK_COMMAND_CHAR(tok) + g_token->name));
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a %s",
+ qPrint(TK_COMMAND_CHAR(tok) + g_token->name), txt);
+ break;
+ case TK_SYMBOL:
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found found as part of a %s",
+ qPrint(g_token->name), txt);
+ break;
+ case TK_EMOJI:
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported emoji '%s' found while handling command %s",
+ qPrint(g_token->name),txt);
+ break;
+ default:
+ children.append(new DocWord(parent,g_token->name));
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s found as part of a %s",
+ tokToString(tok), txt);
+ break;
+ }
+}
+//---------------------------------------------------------------------------
// forward declaration
static bool defaultHandleToken(DocNode *parent,int tok,
QList<DocNode> &children,bool
@@ -876,6 +908,7 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children,
const QCString &cmdName)
{
DBG(("handleStyleArgument(%s)\n",qPrint(cmdName)));
+ QCString saveCmdName = cmdName;
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
@@ -901,14 +934,6 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children,
{
switch (tok)
{
- case TK_COMMAND:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command \\%s as the argument of a \\%s command",
- qPrint(g_token->name),qPrint(cmdName));
- break;
- case TK_SYMBOL:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found while handling command %s",
- qPrint(g_token->name),qPrint(cmdName));
- break;
case TK_HTMLTAG:
if (insideLI(parent) && Mappers::htmlTagMapper->map(g_token->name) && g_token->endTag)
{ // ignore </li> as the end of a style command
@@ -917,8 +942,7 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children,
return tok;
break;
default:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s while handling command %s",
- tokToString(tok),qPrint(cmdName));
+ errorHandleDefaultToken(parent,tok,children,"\\" + saveCmdName + " command");
break;
}
break;
@@ -1297,21 +1321,7 @@ static void defaultHandleTitleAndSize(const int cmd, DocNode *parent, QList<DocN
}
if (!defaultHandleToken(parent,tok,children))
{
- switch (tok)
- {
- case TK_COMMAND:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\%s",
- qPrint(g_token->name), Mappers::cmdMapper->find(cmd).data());
- break;
- case TK_SYMBOL:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
- qPrint(g_token->name));
- break;
- default:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
- tokToString(tok));
- break;
- }
+ errorHandleDefaultToken(parent,tok,children,Mappers::cmdMapper->find(cmd).data());
}
}
// parse size attributes
@@ -1369,8 +1379,8 @@ static bool defaultHandleToken(DocNode *parent,int tok, QList<DocNode> &children
handleWord)
{
DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno));
- if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL ||
- tok==TK_COMMAND || tok==TK_HTMLTAG
+ if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_EMOJI || tok==TK_URL ||
+ tok==TK_COMMAND_AT || tok==TK_COMMAND_BS || tok==TK_HTMLTAG
)
{
DBG((" name=%s",qPrint(g_token->name)));
@@ -1380,7 +1390,9 @@ reparsetoken:
QCString tokenName = g_token->name;
switch (tok)
{
- case TK_COMMAND:
+ case TK_COMMAND_AT:
+ // fall through
+ case TK_COMMAND_BS:
switch (Mappers::cmdMapper->map(tokenName))
{
case CMD_BSLASH:
@@ -1404,6 +1416,9 @@ reparsetoken:
case CMD_HASH:
children.append(new DocSymbol(parent,DocSymbol::Sym_Hash));
break;
+ case CMD_COLON:
+ children.append(new DocSymbol(parent,DocSymbol::Sym_Colon));
+ break;
case CMD_DCOLON:
children.append(new DocSymbol(parent,DocSymbol::Sym_DoubleColon));
break;
@@ -1564,6 +1579,9 @@ reparsetoken:
doctokenizerYYsetStatePara();
}
break;
+ case CMD_IMAGE:
+ ((DocPara *)parent) -> handleImage("image");
+ break;
default:
return FALSE;
}
@@ -1692,6 +1710,19 @@ reparsetoken:
}
}
break;
+ case TK_EMOJI:
+ {
+ int s = DocEmoji::decodeEmoji(tokenName);
+ if (s!=0)
+ {
+ children.append(new DocEmoji(parent,s));
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ break;
case TK_WHITESPACE:
case TK_NEWPARA:
handlepara:
@@ -1750,7 +1781,8 @@ static void handleImg(DocNode *parent,QList<DocNode> &children,const HtmlAttribL
// and remove the src attribute
bool result = attrList.remove(index);
ASSERT(result);
- DocImage *img = new DocImage(parent,attrList,opt->value,DocImage::Html,opt->value);
+ DocImage::Type t = DocImage::Html;
+ DocImage *img = new DocImage(parent,attrList,findAndCopyImage(opt->value,t,false),t,opt->value);
children.append(img);
found = TRUE;
}
@@ -1769,6 +1801,12 @@ DocSymbol::SymType DocSymbol::decodeSymbol(const QCString &symName)
return HtmlEntityMapper::instance()->name2sym(symName);
}
+int DocEmoji::decodeEmoji(const QCString &symName)
+{
+ DBG(("decodeSymbol(%s)\n",qPrint(symName)));
+ return EmojiEntityMapper::instance()->name2sym(symName);
+}
+
//---------------------------------------------------------------------------
static int internalValidatingParseDoc(DocNode *parent,QList<DocNode> &children,
@@ -1900,11 +1938,8 @@ DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor)
{
warn_doc_error(g_fileName,doctokenizerYYlineno,"Empty anchor label");
}
- if (newAnchor) // found <a name="label">
- {
- m_anchor = id;
- }
- else if (id.left(CiteConsts::anchorPrefix.length()) == CiteConsts::anchorPrefix)
+
+ if (id.left(CiteConsts::anchorPrefix.length()) == CiteConsts::anchorPrefix)
{
CiteInfo *cite = Doxygen::citeDict->find(id.mid(CiteConsts::anchorPrefix.length()));
if (cite)
@@ -1919,6 +1954,10 @@ DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor)
m_file = "invalid";
}
}
+ else if (newAnchor) // found <a name="label">
+ {
+ m_anchor = id;
+ }
else // found \anchor label
{
SectionInfo *sec = Doxygen::sectionDict->find(id);
@@ -2330,21 +2369,7 @@ void DocSecRefItem::parse()
{
if (!defaultHandleToken(this,tok,m_children))
{
- switch (tok)
- {
- case TK_COMMAND:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\refitem",
- qPrint(g_token->name));
- break;
- case TK_SYMBOL:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
- qPrint(g_token->name));
- break;
- default:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
- tokToString(tok));
- break;
- }
+ errorHandleDefaultToken(this,tok,m_children,"\\refitem");
}
}
doctokenizerYYsetStatePara();
@@ -2392,7 +2417,7 @@ void DocSecRefList::parse()
// handle items
while (tok)
{
- if (tok==TK_COMMAND)
+ if (tok==TK_COMMAND_AT || tok == TK_COMMAND_BS)
{
switch (Mappers::cmdMapper->map(g_token->name))
{
@@ -2472,21 +2497,7 @@ void DocInternalRef::parse()
{
if (!defaultHandleToken(this,tok,m_children))
{
- switch (tok)
- {
- case TK_COMMAND:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\ref",
- qPrint(g_token->name));
- break;
- case TK_SYMBOL:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
- qPrint(g_token->name));
- break;
- default:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
- tokToString(tok));
- break;
- }
+ errorHandleDefaultToken(this,tok,m_children,"\\ref");
}
}
@@ -2630,19 +2641,10 @@ void DocRef::parse()
{
switch (tok)
{
- case TK_COMMAND:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\ref",
- qPrint(g_token->name));
- break;
- case TK_SYMBOL:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
- qPrint(g_token->name));
- break;
case TK_HTMLTAG:
break;
default:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
- tokToString(tok));
+ errorHandleDefaultToken(this,tok,m_children,"\\ref");
break;
}
}
@@ -2753,7 +2755,9 @@ QCString DocLink::parse(bool isJavaLink,bool isXmlLink)
{
switch (tok)
{
- case TK_COMMAND:
+ case TK_COMMAND_AT:
+ // fall through
+ case TK_COMMAND_BS:
switch (Mappers::cmdMapper->map(g_token->name))
{
case CMD_ENDLINK:
@@ -2769,13 +2773,17 @@ QCString DocLink::parse(bool isJavaLink,bool isXmlLink)
}
break;
case TK_SYMBOL:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found as part of a \\link",
+ qPrint(g_token->name));
+ break;
+ case TK_EMOJI:
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported emoji '%s' found",
qPrint(g_token->name));
break;
case TK_HTMLTAG:
if (g_token->name!="see" || !isXmlLink)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected xml/html command %s found",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected xml/html command %s found as part of a \\link",
qPrint(g_token->name));
}
goto endlink;
@@ -2953,21 +2961,7 @@ void DocVhdlFlow::parse()
{
if (!defaultHandleToken(this,tok,m_children))
{
- switch (tok)
- {
- case TK_COMMAND:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\vhdlflow",
- qPrint(g_token->name));
- break;
- case TK_SYMBOL:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
- qPrint(g_token->name));
- break;
- default:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
- tokToString(tok));
- break;
- }
+ errorHandleDefaultToken(this,tok,m_children,"\\vhdlflow");
}
}
tok=doctokenizerYYlex();
@@ -2985,10 +2979,10 @@ void DocVhdlFlow::parse()
//---------------------------------------------------------------------------
DocImage::DocImage(DocNode *parent,const HtmlAttribList &attribs,const QCString &name,
- Type t,const QCString &url) :
- m_attribs(attribs), m_name(name),
+ Type t,const QCString &url, bool inlineImage) :
+ m_attribs(attribs), m_name(name),
m_type(t), m_relPath(g_relPath),
- m_url(url)
+ m_url(url), m_inlineImage(inlineImage)
{
m_parent = parent;
}
@@ -3014,10 +3008,6 @@ int DocHtmlHeader::parse()
{
switch (tok)
{
- case TK_COMMAND:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a <h%d> tag",
- qPrint(g_token->name),m_level);
- break;
case TK_HTMLTAG:
{
int tagId=Mappers::htmlTagMapper->map(g_token->name);
@@ -3092,17 +3082,12 @@ int DocHtmlHeader::parse()
warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <h%d> context",
g_token->endTag?"/":"",qPrint(g_token->name),m_level);
}
-
}
break;
- case TK_SYMBOL:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
- qPrint(g_token->name));
- break;
default:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
- tokToString(tok));
- break;
+ char tmp[20];
+ sprintf(tmp,"<h%d>tag",m_level);
+ errorHandleDefaultToken(this,tok,m_children,tmp);
}
}
}
@@ -3134,16 +3119,7 @@ int DocHRef::parse()
{
switch (tok)
{
- case TK_COMMAND:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a <a>..</a> block",
- qPrint(g_token->name));
- break;
- case TK_SYMBOL:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
- qPrint(g_token->name));
- break;
case TK_HTMLTAG:
-
{
int tagId=Mappers::htmlTagMapper->map(g_token->name);
if (tagId==HTML_A && g_token->endTag) // found </a> tag
@@ -3158,8 +3134,7 @@ int DocHRef::parse()
}
break;
default:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
- tokToString(tok),doctokenizerYYlineno);
+ errorHandleDefaultToken(this,tok,m_children,"<a>..</a> block");
break;
}
}
@@ -3292,29 +3267,45 @@ int DocIndexEntry::parse()
}
}
break;
- case TK_COMMAND:
- switch (Mappers::cmdMapper->map(g_token->name))
- {
- case CMD_BSLASH: m_entry+='\\'; break;
- case CMD_AT: m_entry+='@'; break;
- case CMD_LESS: m_entry+='<'; break;
- case CMD_GREATER: m_entry+='>'; break;
- case CMD_AMP: m_entry+='&'; break;
- case CMD_DOLLAR: m_entry+='$'; break;
- case CMD_HASH: m_entry+='#'; break;
- case CMD_DCOLON: m_entry+="::"; break;
- case CMD_PERCENT: m_entry+='%'; break;
- case CMD_NDASH: m_entry+="--"; break;
- case CMD_MDASH: m_entry+="---"; break;
- case CMD_QUOTE: m_entry+='"'; break;
- case CMD_PUNT: m_entry+='.'; break;
- case CMD_PLUS: m_entry+='+'; break;
- case CMD_MINUS: m_entry+='-'; break;
- default:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected command %s found as argument of \\addindex",
- qPrint(g_token->name));
- break;
- }
+ case TK_EMOJI:
+ {
+ int s = DocEmoji::decodeEmoji(g_token->name);
+ if (s != 0)
+ {
+ m_entry+=g_token->name;
+ }
+ else
+ {
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected emoji found as argument of \\addindex");
+ }
+ }
+ break;
+ case TK_COMMAND_AT:
+ // fall through
+ case TK_COMMAND_BS:
+ switch (Mappers::cmdMapper->map(g_token->name))
+ {
+ case CMD_BSLASH: m_entry+='\\'; break;
+ case CMD_AT: m_entry+='@'; break;
+ case CMD_LESS: m_entry+='<'; break;
+ case CMD_GREATER: m_entry+='>'; break;
+ case CMD_AMP: m_entry+='&'; break;
+ case CMD_DOLLAR: m_entry+='$'; break;
+ case CMD_HASH: m_entry+='#'; break;
+ case CMD_COLON: m_entry+=":"; break;
+ case CMD_DCOLON: m_entry+="::"; break;
+ case CMD_PERCENT: m_entry+='%'; break;
+ case CMD_NDASH: m_entry+="--"; break;
+ case CMD_MDASH: m_entry+="---"; break;
+ case CMD_QUOTE: m_entry+='"'; break;
+ case CMD_PUNT: m_entry+='.'; break;
+ case CMD_PLUS: m_entry+='+'; break;
+ case CMD_MINUS: m_entry+='-'; break;
+ default:
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected command %s found as argument of \\addindex",
+ qPrint(g_token->name));
+ break;
+ }
break;
default:
warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
@@ -3380,14 +3371,6 @@ int DocHtmlCaption::parse()
{
switch (tok)
{
- case TK_COMMAND:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a <caption> tag",
- qPrint(g_token->name));
- break;
- case TK_SYMBOL:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
- qPrint(g_token->name));
- break;
case TK_HTMLTAG:
{
int tagId=Mappers::htmlTagMapper->map(g_token->name);
@@ -3404,8 +3387,7 @@ int DocHtmlCaption::parse()
}
break;
default:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
- tokToString(tok));
+ errorHandleDefaultToken(this,tok,m_children,"<caption> tag");
break;
}
}
@@ -3919,7 +3901,9 @@ int DocHtmlDescTitle::parse()
{
switch (tok)
{
- case TK_COMMAND:
+ case TK_COMMAND_AT:
+ // fall through
+ case TK_COMMAND_BS:
{
QCString cmdName=g_token->name;
bool isJavaLink=FALSE;
@@ -3930,7 +3914,7 @@ int DocHtmlDescTitle::parse()
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
qPrint(g_token->name));
}
else
@@ -3939,7 +3923,7 @@ int DocHtmlDescTitle::parse()
tok=doctokenizerYYlex(); // get the reference id
if (tok!=TK_WORD)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of \\%s command",
tokToString(tok),qPrint(cmdName));
}
else
@@ -3960,7 +3944,7 @@ int DocHtmlDescTitle::parse()
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
qPrint(cmdName));
}
else
@@ -3969,7 +3953,7 @@ int DocHtmlDescTitle::parse()
tok=doctokenizerYYlex();
if (tok!=TK_WORD)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of \\%s command",
tokToString(tok),qPrint(cmdName));
}
else
@@ -3988,13 +3972,17 @@ int DocHtmlDescTitle::parse()
break;
default:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a <dt> tag",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command \\%s found as part of a <dt> tag",
qPrint(g_token->name));
}
}
break;
case TK_SYMBOL:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol \\%s found as part of a <dt> tag",
+ qPrint(g_token->name));
+ break;
+ case TK_EMOJI:
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported emoji '%s' found",
qPrint(g_token->name));
break;
case TK_HTMLTAG:
@@ -4035,7 +4023,7 @@ int DocHtmlDescTitle::parse()
}
break;
default:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s found as part of a <dt> tag",
tokToString(tok));
break;
}
@@ -4540,21 +4528,7 @@ void DocTitle::parse()
{
if (!defaultHandleToken(this,tok,m_children))
{
- switch (tok)
- {
- case TK_COMMAND:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a title section",
- qPrint(g_token->name));
- break;
- case TK_SYMBOL:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found",
- qPrint(g_token->name));
- break;
- default:
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s",
- tokToString(tok));
- break;
- }
+ errorHandleDefaultToken(this,tok,m_children,"title section");
}
}
doctokenizerYYsetStatePara();
@@ -5088,13 +5062,50 @@ void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type
void DocPara::handleImage(const QCString &cmdName)
{
QCString saveCmdName = cmdName;
+ bool inlineImage = FALSE;
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
+ if (tok==TK_WORD)
+ {
+ if (g_token->name == "{")
+ {
+ while ((tok=doctokenizerYYlex())==TK_WHITESPACE);
+ if (g_token->name != "}") // non-empty option string
+ {
+ if (g_token->name.lower() != "inline")
+ {
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"currently only 'inline' suported as option of %s command",
+ qPrint(saveCmdName));
+ }
+ else
+ {
+ inlineImage = TRUE;
+ }
+ while ((tok=doctokenizerYYlex())==TK_WHITESPACE);
+ }
+ if (!((tok==TK_WORD) && (g_token->name == "}")))
+ {
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected closing '}' at option of %s command",
+ qPrint(saveCmdName));
+ return;
+ }
+ tok=doctokenizerYYlex();
+ if (tok!=TK_WHITESPACE)
+ {
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command with option",
+ qPrint(saveCmdName));
+ return;
+ }
+ }
+ }
+ else
+ {
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
qPrint(saveCmdName));
- return;
+ return;
+ }
}
tok=doctokenizerYYlex();
if (tok!=TK_WORD && tok!=TK_LNKWORD)
@@ -5133,7 +5144,7 @@ void DocPara::handleImage(const QCString &cmdName)
return;
}
HtmlAttribList attrList;
- DocImage *img = new DocImage(this,attrList,findAndCopyImage(g_token->name,t),t);
+ DocImage *img = new DocImage(this,attrList,findAndCopyImage(g_token->name,t),t,"",inlineImage);
m_children.append(img);
img->parse();
}
@@ -5415,7 +5426,7 @@ void DocPara::handleInheritDoc()
}
-int DocPara::handleCommand(const QCString &cmdName)
+int DocPara::handleCommand(const QCString &cmdName, const int tok)
{
DBG(("handleCommand(%s)\n",qPrint(cmdName)));
int retval = RetVal_OK;
@@ -5423,6 +5434,7 @@ int DocPara::handleCommand(const QCString &cmdName)
switch (cmdId)
{
case CMD_UNKNOWN:
+ m_children.append(new DocWord(this,TK_COMMAND_CHAR(tok) + cmdName));
warn_doc_error(g_fileName,doctokenizerYYlineno,"Found unknown command `\\%s'",qPrint(cmdName));
break;
case CMD_EMPHASIS:
@@ -5467,6 +5479,9 @@ int DocPara::handleCommand(const QCString &cmdName)
case CMD_PIPE:
m_children.append(new DocSymbol(this,DocSymbol::Sym_Pipe));
break;
+ case CMD_COLON:
+ m_children.append(new DocSymbol(this,DocSymbol::Sym_Colon));
+ break;
case CMD_DCOLON:
m_children.append(new DocSymbol(this,DocSymbol::Sym_DoubleColon));
break;
@@ -6524,8 +6539,8 @@ int DocPara::parse()
{
reparsetoken:
DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno));
- if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL ||
- tok==TK_COMMAND || tok==TK_HTMLTAG
+ if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_EMOJI || tok==TK_URL ||
+ tok==TK_COMMAND_AT || tok == TK_COMMAND_BS || tok==TK_HTMLTAG
)
{
DBG((" name=%s",qPrint(g_token->name)));
@@ -6623,7 +6638,7 @@ reparsetoken:
}
else // other section
{
- tok = TK_COMMAND;
+ tok = TK_COMMAND_BS;
}
DBG(("reparsing command %s\n",qPrint(g_token->name)));
goto reparsetoken;
@@ -6668,7 +6683,9 @@ reparsetoken:
"list items");
}
break;
- case TK_COMMAND:
+ case TK_COMMAND_AT:
+ // fall through
+ case TK_COMMAND_BS:
{
// see if we have to start a simple section
int cmd = Mappers::cmdMapper->map(g_token->name);
@@ -6704,7 +6721,7 @@ reparsetoken:
}
// handle the command
- retval=handleCommand(g_token->name);
+ retval=handleCommand(g_token->name,tok);
DBG(("handleCommand returns %x\n",retval));
// check the return value
@@ -6722,7 +6739,7 @@ reparsetoken:
}
else // other section
{
- tok = TK_COMMAND;
+ tok = TK_COMMAND_BS;
}
DBG(("reparsing command %s\n",qPrint(g_token->name)));
goto reparsetoken;
@@ -6780,6 +6797,20 @@ reparsetoken:
}
break;
}
+ case TK_EMOJI:
+ {
+ int s = DocEmoji::decodeEmoji(g_token->name);
+ if (s!=0)
+ {
+ m_children.append(new DocEmoji(this,s));
+ }
+ else
+ {
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported emoji '%s' found",
+ qPrint(g_token->name));
+ }
+ break;
+ }
case TK_NEWPARA:
retval=TK_NEWPARA;
goto endparagraph;
@@ -6994,7 +7025,23 @@ void DocText::parse()
}
}
break;
- case TK_COMMAND:
+ case TK_EMOJI:
+ {
+ int s = DocSymbol::decodeSymbol(g_token->name);
+ if (s!=0)
+ {
+ m_children.append(new DocEmoji(this,s));
+ }
+ else
+ {
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported emoji '%s' found",
+ qPrint(g_token->name));
+ }
+ }
+ break;
+ case TK_COMMAND_AT:
+ // fall through
+ case TK_COMMAND_BS:
switch (Mappers::cmdMapper->map(g_token->name))
{
case CMD_BSLASH:
@@ -7018,6 +7065,9 @@ void DocText::parse()
case CMD_HASH:
m_children.append(new DocSymbol(this,DocSymbol::Sym_Hash));
break;
+ case CMD_COLON:
+ m_children.append(new DocSymbol(this,DocSymbol::Sym_Colon));
+ break;
case CMD_DCOLON:
m_children.append(new DocSymbol(this,DocSymbol::Sym_DoubleColon));
break;
@@ -7413,7 +7463,7 @@ QString::Direction getTextDirByConfig(const DocPara *para, int nodeIndex)
return QString::DirNeutral;
}
-QCString getDirHtmlClassOfNode(QString::Direction textDir, const char *initValue)
+QCString getDirHtmlClassOfNode(QString::Direction textDir, const QCString &initValue)
{
QCString classFromDir;
if (textDir == QString::DirLTR)
@@ -7423,9 +7473,9 @@ QCString getDirHtmlClassOfNode(QString::Direction textDir, const char *initValue
else
classFromDir = "";
- if (initValue != NULL && !classFromDir.isEmpty())
+ if (initValue && !classFromDir.isEmpty())
return QCString(" class=\"") + initValue + " " + classFromDir + "\"";
- if (initValue != NULL)
+ if (initValue)
return QCString(" class=\"") + initValue + "\"";
if (!classFromDir.isEmpty())
return QCString(" class=\"") + classFromDir + "\"";
diff --git a/src/docparser.h b/src/docparser.h
index 68f9fc1..6274f40 100644
--- a/src/docparser.h
+++ b/src/docparser.h
@@ -37,7 +37,7 @@ class SectionDict;
QString::Direction getTextDirByConfig(const QString &text);
QString::Direction getTextDirByConfig(const DocNode *node);
QString::Direction getTextDirByConfig(const DocPara *para, int nodeIndex);
-QCString getDirHtmlClassOfNode(QString::Direction textDir, const char *initValue = NULL);
+QCString getDirHtmlClassOfNode(QString::Direction textDir, const QCString &initValue="");
QCString getDirHtmlClassOfPage(QCString pageTitle);
QCString getHtmlDirEmbedingChar(QString::Direction textDir);
QCString getJsDirEmbedingChar(QString::Direction textDir);
@@ -140,7 +140,8 @@ class DocNode
Kind_HtmlBlockQuote = 49,
Kind_VhdlFlow = 50,
Kind_ParBlock = 51,
- Kind_DiaFile = 52
+ Kind_DiaFile = 52,
+ Kind_Emoji = 53
};
/*! Creates a new node */
DocNode() : m_parent(0), m_insidePre(FALSE) {}
@@ -454,7 +455,7 @@ class DocSymbol : public DocNode
/* doxygen commands mapped */
Sym_BSlash, Sym_At, Sym_Less, Sym_Greater, Sym_Amp,
Sym_Dollar, Sym_Hash, Sym_DoubleColon, Sym_Percent, Sym_Pipe,
- Sym_Quot, Sym_Minus, Sym_Plus, Sym_Dot
+ Sym_Quot, Sym_Minus, Sym_Plus, Sym_Dot, Sym_Colon
};
enum PerlType { Perl_unknown = 0, Perl_string, Perl_char, Perl_symbol, Perl_umlaut,
Perl_acute, Perl_grave, Perl_circ, Perl_slash, Perl_tilde,
@@ -475,6 +476,21 @@ class DocSymbol : public DocNode
SymType m_symbol;
};
+/** Node representing a n emoji */
+class DocEmoji : public DocNode
+{
+ public:
+ DocEmoji(DocNode *parent,int s) :
+ m_symbol(s) { m_parent = parent; }
+ int emoji() const { return m_symbol; }
+ Kind kind() const { return Kind_Emoji; }
+ void accept(DocVisitor *v) { v->visit(this); }
+ static int decodeEmoji(const QCString &symName);
+
+ private:
+ int m_symbol;
+};
+
/** Node representing some amount of white space */
class DocWhiteSpace : public DocNode
{
@@ -740,7 +756,7 @@ class DocImage : public CompAccept<DocImage>
public:
enum Type { Html, Latex, Rtf, DocBook };
DocImage(DocNode *parent,const HtmlAttribList &attribs,
- const QCString &name,Type t,const QCString &url=QCString());
+ const QCString &name,Type t,const QCString &url=QCString(), bool inlineImage = TRUE);
Kind kind() const { return Kind_Image; }
Type type() const { return m_type; }
QCString name() const { return m_name; }
@@ -749,6 +765,7 @@ class DocImage : public CompAccept<DocImage>
QCString height() const { return m_height; }
QCString relPath() const { return m_relPath; }
QCString url() const { return m_url; }
+ bool isInlineImage() const { return m_inlineImage; }
const HtmlAttribList &attribs() const { return m_attribs; }
void parse();
@@ -760,6 +777,7 @@ class DocImage : public CompAccept<DocImage>
QCString m_height;
QCString m_relPath;
QCString m_url;
+ bool m_inlineImage;
};
/** Node representing a dot file */
@@ -1155,7 +1173,7 @@ class DocPara : public CompAccept<DocPara>
bool isFirst() const { return m_isFirst; }
bool isLast() const { return m_isLast; }
- int handleCommand(const QCString &cmdName);
+ int handleCommand(const QCString &cmdName,const int tok);
int handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &tagHtmlAttribs);
int handleHtmlEndTag(const QCString &tagName);
int handleSimpleSection(DocSimpleSect::Type t,bool xmlContext=FALSE);
diff --git a/src/docsets.cpp b/src/docsets.cpp
index 29b7616..1327d80 100644
--- a/src/docsets.cpp
+++ b/src/docsets.cpp
@@ -334,6 +334,7 @@ void DocSets::addIndexItem(Definition *context,MemberDef *md,
case SrcLangExt_SQL: lang="sql"; break; // Sql
case SrcLangExt_Tcl: lang="tcl"; break; // Tcl
case SrcLangExt_Markdown:lang="markdown"; break; // Markdown
+ case SrcLangExt_Slice: lang="slice"; break; // Slice
case SrcLangExt_Unknown: lang="unknown"; break; // should not happen!
}
@@ -401,6 +402,10 @@ void DocSets::addIndexItem(Definition *context,MemberDef *md,
type="ifc"; break;
case MemberType_Service:
type="svc"; break;
+ case MemberType_Sequence:
+ type="sequence"; break;
+ case MemberType_Dictionary:
+ type="dictionary"; break;
}
cd = md->getClassDef();
nd = md->getNamespaceDef();
diff --git a/src/doctokenizer.h b/src/doctokenizer.h
index b3b9fa5..f510c33 100644
--- a/src/doctokenizer.h
+++ b/src/doctokenizer.h
@@ -34,12 +34,14 @@ enum Tokens
TK_WHITESPACE = 3,
TK_LISTITEM = 4,
TK_ENDLIST = 5,
- TK_COMMAND = 6,
+ TK_COMMAND_AT = 6, //! Command starting with `@`
TK_HTMLTAG = 7,
TK_SYMBOL = 8,
TK_NEWPARA = 9,
TK_RCSTAG = 10,
TK_URL = 11,
+ TK_COMMAND_BS = 12, //! Command starting with `\`
+ TK_EMOJI = 13,
RetVal_OK = 0x10000,
RetVal_SimpleSec = 0x10001,
diff --git a/src/doctokenizer.l b/src/doctokenizer.l
index 3118cfd..f50b9ae 100644
--- a/src/doctokenizer.l
+++ b/src/doctokenizer.l
@@ -38,9 +38,12 @@
#include "definition.h"
#include "doxygen.h"
#include "portable.h"
+#include "cite.h"
#define YY_NO_INPUT 1
#define YY_NO_UNISTD_H 1
+
+#define TK_COMMAND_SEL() (yytext[0] == '@' ? TK_COMMAND_AT : TK_COMMAND_BS)
//--------------------------------------------------------------------------
@@ -116,12 +119,14 @@ const char *tokToString(int token)
case TK_WHITESPACE: return "TK_WHITESPACE";
case TK_LISTITEM: return "TK_LISTITEM";
case TK_ENDLIST: return "TK_ENDLIST";
- case TK_COMMAND: return "TK_COMMAND";
+ case TK_COMMAND_AT: return "TK_COMMAND_AT";
case TK_HTMLTAG: return "TK_HTMLTAG";
case TK_SYMBOL: return "TK_SYMBOL";
case TK_NEWPARA: return "TK_NEWPARA";
case TK_RCSTAG: return "TK_RCSTAG";
case TK_URL: return "TK_URL";
+ case TK_COMMAND_BS: return "TK_COMMAND_BS";
+ case TK_EMOJI: return "TK_EMOJI";
}
return "ERROR";
}
@@ -332,12 +337,13 @@ CMD ("\\"|"@")
WS [ \t\r\n]
NONWS [^ \t\r\n]
BLANK [ \t\r]
+EMOJI (":"[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"'+()&\*\.!,#-]":")
ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
LABELID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]*
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 [a-z_A-Z0-9\x80-\xFF\-\?]
+CITEECHAR [a-z_A-Z0-9\x80-\xFF\-\+:\/\?]
+CITEID {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*|"\""{CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*"\""
MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+
OPTSTARS ("//"{BLANK}*)?"*"*{BLANK}*
LISTITEM {BLANK}*[-]("#")?{WS}
@@ -358,6 +364,7 @@ SPCMD1 {CMD}([a-z_A-Z][a-z_A-Z0-9]*|{VERBATIM}|"--"|"---")
SPCMD2 {CMD}[\\@<>&$#%~".+|-]
SPCMD3 {CMD}form#[0-9]+
SPCMD4 {CMD}"::"
+SPCMD5 {CMD}":"
INOUT "inout"|"in"|"out"|("in"{BLANK}*","{BLANK}*"out")|("out"{BLANK}*","{BLANK}*"in")
PARAMIO {CMD}param{BLANK}*"["{BLANK}*{INOUT}{BLANK}*"]"
VARARGS "..."
@@ -389,9 +396,9 @@ CHARWORDQ [^ \t\n\r\\@<>()\[\]:;\?{}&%$#,."=']
ESCWORD ("%"{ID}(("::"|"."){ID})*)|("%'")
CHARWORDQ1 [^ \-+0-9\t\n\r\\@<>()\[\]:;\?{}&%$#,."=']
WORD1 {ESCWORD}|{CHARWORDQ1}{CHARWORDQ}*|"{"|"}"|"'\"'"|("\""[^"\n]*\n?[^"\n]*"\"")
-WORD2 "."|","|"("|")"|"["|"]"|":"|";"|"\?"|"="|"'"
+WORD2 "."|","|"("|")"|"["|"]"|"::"|":"|";"|"\?"|"="|"'"
WORD1NQ {ESCWORD}|{CHARWORDQ}+|"{"|"}"
-WORD2NQ "."|","|"("|")"|"["|"]"|":"|";"|"\?"|"="|"'"
+WORD2NQ "."|","|"("|")"|"["|"]"|"::"|":"|";"|"\?"|"="|"'"
CAPTION [cC][aA][pP][tT][iI][oO][nN]
HTMLTAG "<"(("/")?){ID}({WS}+{ATTRIB})*{WS}*(("/")?)">"
HTMLKEYL "strong"|"center"|"table"|"caption"|"small"|"code"|"dfn"|"var"|"img"|"pre"|"sub"|"sup"|"tr"|"td"|"th"|"ol"|"ul"|"li"|"tt"|"kbd"|"em"|"hr"|"dl"|"dt"|"dd"|"br"|"i"|"a"|"b"|"p"|"strike"|"u"
@@ -403,8 +410,8 @@ REFWORD2_NOCV {REFWORD2_PRE}("("{FUNCPART}")")?
REFWORD3 ({ID}":")*{ID}":"?
REFWORD4_NOCV (({SCOPEPRE}*"operator"{OPMASKOP2})|(("::"|"#"){SCOPEPRE}*"operator"{OPMASKOP2}))
REFWORD4 {REFWORD4_NOCV}{CVSPEC}?
-REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{REFWORD4}
-REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
+REFWORD {FILEMASK}|{LABELID}|{REFWORD2}|{REFWORD3}|{REFWORD4}
+REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
%option noyywrap
%option yylineno
@@ -558,11 +565,11 @@ REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
}
<St_Para>"{"{BLANK}*"@link"/{BLANK}+ {
g_token->name = "javalink";
- return TK_COMMAND;
+ return TK_COMMAND_AT;
}
<St_Para>"{"{BLANK}*"@inheritDoc"{BLANK}*"}" {
g_token->name = "inheritdoc";
- return TK_COMMAND;
+ return TK_COMMAND_AT;
}
<St_Para>"@_fakenl" { // artificial new line
yylineno++;
@@ -572,22 +579,23 @@ REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
bool ok;
g_token->id = QCString(yytext).right((int)yyleng-6).toInt(&ok);
ASSERT(ok);
- return TK_COMMAND;
+ return TK_COMMAND_SEL();
}
<St_Para>{CMD}"n"\n { /* \n followed by real newline */
yylineno++;
g_token->name = yytext+1;
g_token->name = g_token->name.stripWhiteSpace();
g_token->paramDir=TokenInfo::Unspecified;
- return TK_COMMAND;
+ return TK_COMMAND_SEL();
}
<St_Para>{SPCMD1} |
<St_Para>{SPCMD2} |
+<St_Para>{SPCMD5} |
<St_Para>{SPCMD4} { /* special command */
g_token->name = yytext+1;
g_token->name = g_token->name.stripWhiteSpace();
g_token->paramDir=TokenInfo::Unspecified;
- return TK_COMMAND;
+ return TK_COMMAND_SEL();
}
<St_Para>{PARAMIO} { /* param [in,out] command */
g_token->name = "param";
@@ -613,7 +621,7 @@ REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
{
g_token->paramDir=TokenInfo::Unspecified;
}
- return TK_COMMAND;
+ return TK_COMMAND_SEL();
}
<St_Para>("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK}/\. { // URL.
g_token->name=yytext;
@@ -674,6 +682,17 @@ REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
g_token->name = yytext;
return TK_SYMBOL;
}
+<St_Para,St_Text>{EMOJI} { /* emoji symbol */
+ if (g_fileName == CiteConsts::fileName)
+ {
+ REJECT;
+ }
+ else
+ {
+ g_token->name = yytext;
+ return TK_EMOJI;
+ }
+ }
/********* patterns for linkable words ******************/
@@ -733,7 +752,7 @@ REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
}
<St_Text>[\\@<>&$#%~] {
g_token->name = yytext;
- return TK_COMMAND;
+ return TK_COMMAND_SEL();
}
<St_Para>({BLANK}*\n)+{BLANK}*\n/{LISTITEM} { /* skip trailing paragraph followed by new list item */
if (g_insidePre || g_autoListLevel==0)
@@ -920,13 +939,24 @@ REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
g_token->name = yytext;
return TK_SYMBOL;
}
+<St_TitleN>{EMOJI} { /* emoji */
+ if (g_fileName == CiteConsts::fileName)
+ {
+ REJECT;
+ }
+ else
+ {
+ g_token->name = yytext;
+ return TK_EMOJI;
+ }
+ }
<St_TitleN>{HTMLTAG} {
}
<St_TitleN>{SPCMD1} |
<St_TitleN>{SPCMD2} { /* special command */
g_token->name = yytext+1;
g_token->paramDir=TokenInfo::Unspecified;
- return TK_COMMAND;
+ return TK_COMMAND_SEL();
}
<St_TitleN>{ID}"=" { /* attribute */
if (yytext[0]=='%') // strip % if present
@@ -956,11 +986,22 @@ REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
g_token->name = yytext;
return TK_SYMBOL;
}
+<St_TitleQ>{EMOJI} { /* emoji */
+ if (g_fileName == CiteConsts::fileName)
+ {
+ REJECT;
+ }
+ else
+ {
+ g_token->name = yytext;
+ return TK_EMOJI;
+ }
+ }
<St_TitleQ>{SPCMD1} |
<St_TitleQ>{SPCMD2} { /* special command */
g_token->name = yytext+1;
g_token->paramDir=TokenInfo::Unspecified;
- return TK_COMMAND;
+ return TK_COMMAND_SEL();
}
<St_TitleQ>{WORD1NQ} |
<St_TitleQ>{WORD2NQ} { /* word */
@@ -1006,7 +1047,15 @@ REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
return 0;
}
<St_Cite>{CITEID} { // label to cite
- g_token->name=yytext;
+ if (yytext[0] =='"')
+ {
+ g_token->name=yytext+1;
+ g_token->name=g_token->name.left(yyleng-2);
+ }
+ else
+ {
+ g_token->name=yytext;
+ }
return TK_WORD;
}
<St_Cite>{BLANK} { // white space
@@ -1055,7 +1104,7 @@ REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
<St_IntRef>{BLANK}+"\"" {
BEGIN(St_Ref2);
}
-<St_SetScope>({SCOPEMASK}|{ANONNS}){BLANK} {
+<St_SetScope>({SCOPEMASK}|{ANONNS}){BLANK}|{FILEMASK} {
g_token->name = yytext;
g_token->name = g_token->name.stripWhiteSpace();
return TK_WORD;
@@ -1087,11 +1136,22 @@ REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
g_token->name = yytext;
return TK_SYMBOL;
}
+<St_Ref2>{EMOJI} { /* emoji */
+ if (g_fileName == CiteConsts::fileName)
+ {
+ REJECT;
+ }
+ else
+ {
+ g_token->name = yytext;
+ return TK_EMOJI;
+ }
+ }
<St_Ref2>{SPCMD1} |
<St_Ref2>{SPCMD2} { /* special command */
g_token->name = yytext+1;
g_token->paramDir=TokenInfo::Unspecified;
- return TK_COMMAND;
+ return TK_COMMAND_SEL();
}
<St_Ref2>{WORD1NQ} |
<St_Ref2>{WORD2NQ} {
@@ -1323,7 +1383,7 @@ REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
<*>[\\@<>&$#%~"=] { /* unescaped special character */
//warn(g_fileName,yylineno,"Unexpected character `%s', assuming command \\%s was meant.",yytext,yytext);
g_token->name = yytext;
- return TK_COMMAND;
+ return TK_COMMAND_SEL();
}
<*>. {
warn(g_fileName,yylineno,"Unexpected character `%s'",yytext);
diff --git a/src/docvisitor.h b/src/docvisitor.h
index 18fb743..d2318c9 100644
--- a/src/docvisitor.h
+++ b/src/docvisitor.h
@@ -37,6 +37,7 @@ class DocAutoListItem;
class DocPara;
class DocRoot;
class DocSymbol;
+class DocEmoji;
class DocURL;
class DocStyleChange;
class DocSimpleSect;
@@ -101,6 +102,7 @@ class DocVisitor
virtual void visit(DocWord *) = 0;
virtual void visit(DocWhiteSpace *) = 0;
virtual void visit(DocSymbol *) = 0;
+ virtual void visit(DocEmoji *) = 0;
virtual void visit(DocURL *) = 0;
virtual void visit(DocStyleChange *) = 0;
virtual void visit(DocVerbatim *) = 0;
diff --git a/src/dot.cpp b/src/dot.cpp
index 5f52210..d82ffa8 100644
--- a/src/dot.cpp
+++ b/src/dot.cpp
@@ -139,7 +139,7 @@ static const char svgZoomFooter[] =
" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
" </g>\n"
" </g>\n"
-// link to orginial SVG
+// link to original SVG
" <svg viewBox=\"0 0 15 15\" width=\"100%\" height=\"30px\" preserveAspectRatio=\"xMaxYMin meet\">\n"
" <g id=\"arrow_out\" transform=\"scale(0.3 0.3)\">\n"
" <a xlink:href=\"$orgname\" target=\"_base\">\n"
@@ -2328,7 +2328,10 @@ void DotGfxHierarchyTable::createGraph(DotNode *n,FTextStream &out,
QCString baseName;
QCString imgExt = getDotImageExtension();
QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT);
- baseName.sprintf("inherit_graph_%d",id);
+ if (m_prefix.isEmpty())
+ baseName.sprintf("inherit_graph_%d",id);
+ else
+ baseName.sprintf("%sinherit_graph_%d",m_prefix.data(),id);
QCString imgName = baseName+"."+ imgExt;
QCString mapName = baseName+".map";
QCString absImgName = QCString(d.absPath().data())+"/"+imgName;
@@ -2520,6 +2523,7 @@ void DotGfxHierarchyTable::addHierarchy(DotNode *n,ClassDef *cd,bool hideSuper)
void DotGfxHierarchyTable::addClassList(ClassSDict *cl)
{
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
ClassSDict::Iterator cli(*cl);
ClassDef *cd;
for (cli.toLast();(cd=cli.current());--cli)
@@ -2531,6 +2535,10 @@ void DotGfxHierarchyTable::addClassList(ClassSDict *cl)
{
continue;
}
+ if (sliceOpt && cd->compoundType() != m_classType)
+ {
+ continue;
+ }
if (!hasVisibleRoot(cd->baseClasses()) &&
cd->isVisibleInHierarchy()
) // root node in the forest
@@ -2563,7 +2571,10 @@ void DotGfxHierarchyTable::addClassList(ClassSDict *cl)
}
}
-DotGfxHierarchyTable::DotGfxHierarchyTable() : m_curNodeNumber(1)
+DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::CompoundType ct)
+ : m_prefix(prefix)
+ , m_classType(ct)
+ , m_curNodeNumber(1)
{
m_rootNodes = new QList<DotNode>;
m_usedNodes = new QDict<DotNode>(1009);
diff --git a/src/dot.h b/src/dot.h
index 3a70d8b..20a1f29 100644
--- a/src/dot.h
+++ b/src/dot.h
@@ -26,8 +26,8 @@
#include <qqueue.h>
#include <qthread.h>
#include "sortdict.h"
+#include "classdef.h"
-class ClassDef;
class FileDef;
class FTextStream;
class DotNodeList;
@@ -156,7 +156,7 @@ class DotNodeList : public QList<DotNode>
class DotGfxHierarchyTable
{
public:
- DotGfxHierarchyTable();
+ DotGfxHierarchyTable(const char *prefix="",ClassDef::CompoundType ct=ClassDef::Class);
~DotGfxHierarchyTable();
void writeGraph(FTextStream &t,const char *path, const char *fileName) const;
void createGraph(DotNode *rootNode,FTextStream &t,const char *path,const char *fileName,int id) const;
@@ -166,10 +166,12 @@ class DotGfxHierarchyTable
void addHierarchy(DotNode *n,ClassDef *cd,bool hide);
void addClassList(ClassSDict *cl);
- QList<DotNode> *m_rootNodes;
- QDict<DotNode> *m_usedNodes;
- int m_curNodeNumber;
- DotNodeList *m_rootSubgraphs;
+ QCString m_prefix;
+ ClassDef::CompoundType m_classType;
+ QList<DotNode> *m_rootNodes;
+ QDict<DotNode> *m_usedNodes;
+ int m_curNodeNumber;
+ DotNodeList *m_rootSubgraphs;
};
/** Representation of a class inheritance or dependency graph */
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
index 1b40db1..e8df763 100644
--- a/src/doxygen.cpp
+++ b/src/doxygen.cpp
@@ -103,6 +103,7 @@
#include "settings.h"
#include "context.h"
#include "fileparser.h"
+#include "emoji.h"
// provided by the generated file resources.cpp
extern void initResources();
@@ -167,6 +168,7 @@ bool Doxygen::suppressDocWarnings = FALSE;
Store *Doxygen::symbolStorage;
QCString Doxygen::objDBFileName;
QCString Doxygen::entryDBFileName;
+QCString Doxygen::filterDBFileName;
bool Doxygen::gatherDefines = TRUE;
IndexList *Doxygen::indexList;
int Doxygen::subpageNestingLevel = 0;
@@ -346,6 +348,7 @@ static STLInfo g_stlinfo[] =
{ "auto_ptr", 0, 0, "T", "ptr", 0, 0, FALSE, FALSE }, // deprecated
{ "smart_ptr", 0, 0, "T", "ptr", 0, 0, FALSE, FALSE }, // C++11
{ "unique_ptr", 0, 0, "T", "ptr", 0, 0, FALSE, FALSE }, // C++11
+ { "shared_ptr", 0, 0, "T", "ptr", 0, 0, FALSE, FALSE }, // C++14
{ "weak_ptr", 0, 0, "T", "ptr", 0, 0, FALSE, FALSE }, // C++11
{ "ios_base", 0, 0, 0, 0, 0, 0, FALSE, FALSE }, // C++11
{ "error_code", 0, 0, 0, 0, 0, 0, FALSE, FALSE }, // C++11
@@ -519,7 +522,7 @@ static void addSTLClasses(EntryNav *rootNav)
{
addSTLMember(classEntryNav,info->templType2,info->templName2);
}
- if (fullName=="std::auto_ptr" || fullName=="std::smart_ptr" ||
+ if (fullName=="std::auto_ptr" || fullName=="std::smart_ptr" || fullName=="std::shared_ptr" ||
fullName=="std::unique_ptr" || fullName=="std::weak_ptr")
{
Entry *memEntry = new Entry;
@@ -1302,6 +1305,8 @@ static void addClassToContext(EntryNav *rootNav)
}
cd->setCompoundType(convertToCompoundType(root->section,root->spec));
+
+ cd->setMetaData(root->metaData);
}
else // new class
{
@@ -1366,6 +1371,8 @@ static void addClassToContext(EntryNav *rootNav)
cd->setBodySegment(root->bodyLine,root->endBodyLine);
cd->setBodyDef(fd);
+ cd->setMetaData(root->metaData);
+
// see if the class is found inside a namespace
//bool found=addNamespace(root,cd);
@@ -1585,7 +1592,7 @@ static ClassDef *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QC
md->typeString(),md->name(),md->argsString(),md->excpString(),
md->protection(),md->virtualness(),md->isStatic(),Member,
md->memberType(),
- 0,0);
+ 0,0,"");
imd->setMemberClass(cd);
imd->setDocumentation(md->documentation(),md->docFile(),md->docLine());
imd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine());
@@ -1757,6 +1764,7 @@ static void buildNamespaceList(EntryNav *rootNav)
nd->setReference("");
nd->setFileName(fullName);
}
+ nd->setMetaData(root->metaData);
// file definition containing the namespace nd
FileDef *fd=rootNav->fileDef();
@@ -1786,6 +1794,7 @@ static void buildNamespaceList(EntryNav *rootNav)
nd->setArtificial(root->artificial);
nd->setLanguage(root->lang);
nd->setId(root->id);
+ nd->setMetaData(root->metaData);
//printf("Adding namespace to group\n");
addNamespaceToGroups(root,nd);
@@ -1961,6 +1970,7 @@ static void findUsingDirectives(EntryNav *rootNav)
nd->setArtificial(TRUE);
nd->setLanguage(root->lang);
nd->setId(root->id);
+ nd->setMetaData(root->metaData);
QListIterator<Grouping> gli(*root->groups);
Grouping *g;
@@ -2166,7 +2176,7 @@ static void findUsingDeclImports(EntryNav *rootNav)
md->typeString(),memName,md->argsString(),
md->excpString(),root->protection,root->virt,
md->isStatic(),Member,md->memberType(),
- templAl,al
+ templAl,al,root->metaData
);
}
newMd->setMemberClass(cd);
@@ -2186,6 +2196,8 @@ static void findUsingDeclImports(EntryNav *rootNav)
newMd->setDefinition(md->definition());
newMd->enableCallGraph(root->callGraph);
newMd->enableCallerGraph(root->callerGraph);
+ newMd->enableReferencedByRelation(root->referencedByRelation);
+ newMd->enableReferencesRelation(root->referencesRelation);
newMd->setBitfields(md->bitfieldString());
newMd->addSectionsToDefinition(root->anchors);
newMd->setBodySegment(md->getStartBodyLine(),md->getEndBodyLine());
@@ -2359,7 +2371,7 @@ static MemberDef *addVariableToClass(
fileName,root->startLine,root->startColumn,
root->type,name,root->args,root->exception,
prot,Normal,root->stat,related,
- mtype,root->tArgLists ? root->tArgLists->getLast() : 0,0);
+ mtype,root->tArgLists ? root->tArgLists->getLast() : 0,0, root->metaData);
md->setTagInfo(rootNav->tagInfo());
md->setMemberClass(cd); // also sets outer scope (i.e. getOuterScope())
//md->setDefFile(root->fileName);
@@ -2382,6 +2394,8 @@ static MemberDef *addVariableToClass(
md->setWriteAccessor(root->write);
md->enableCallGraph(root->callGraph);
md->enableCallerGraph(root->callerGraph);
+ md->enableReferencedByRelation(root->referencedByRelation);
+ md->enableReferencesRelation(root->referencesRelation);
md->setHidden(root->hidden);
md->setArtificial(root->artificial);
md->setLanguage(root->lang);
@@ -2602,7 +2616,7 @@ static MemberDef *addVariableToFile(
fileName,root->startLine,root->startColumn,
root->type,name,root->args,0,
root->protection, Normal,root->stat,Member,
- mtype,root->tArgLists ? root->tArgLists->getLast() : 0,0);
+ mtype,root->tArgLists ? root->tArgLists->getLast() : 0,0, root->metaData);
md->setTagInfo(rootNav->tagInfo());
md->setMemberSpecifiers(root->spec);
md->setDocumentation(root->doc,root->docFile,root->docLine);
@@ -2619,6 +2633,8 @@ static MemberDef *addVariableToFile(
md->setId(root->id);
md->enableCallGraph(root->callGraph);
md->enableCallerGraph(root->callerGraph);
+ md->enableReferencedByRelation(root->referencedByRelation);
+ md->enableReferencesRelation(root->referencesRelation);
md->setExplicitExternal(root->explicitExternal);
//md->setOuterScope(fd);
if (!root->explicitExternal)
@@ -2820,6 +2836,8 @@ done:
static void addVariable(EntryNav *rootNav,int isFuncPtr=-1)
{
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+
rootNav->loadEntry(g_storage);
Entry *root = rootNav->entry();
@@ -2939,6 +2957,10 @@ static void addVariable(EntryNav *rootNav,int isFuncPtr=-1)
mtype=MemberType_Property;
else if (root->mtype==Event)
mtype=MemberType_Event;
+ else if (type.find("sequence<") != -1)
+ mtype=sliceOpt ? MemberType_Sequence : MemberType_Typedef;
+ else if (type.find("dictionary<") != -1)
+ mtype=sliceOpt ? MemberType_Dictionary : MemberType_Typedef;
else
mtype=MemberType_Variable;
@@ -3053,6 +3075,58 @@ static void buildTypedefList(EntryNav *rootNav)
}
//----------------------------------------------------------------------
+// Searches the Entry tree for sequence documentation sections.
+// If found they are stored in the global list.
+static void buildSequenceList(EntryNav *rootNav)
+{
+ if (!rootNav->name().isEmpty() &&
+ rootNav->section()==Entry::VARIABLE_SEC &&
+ rootNav->type().find("sequence<")!=-1 // it's a sequence
+ )
+ {
+ addVariable(rootNav);
+ }
+ if (rootNav->children())
+ {
+ EntryNavListIterator eli(*rootNav->children());
+ EntryNav *e;
+ for (;(e=eli.current());++eli)
+ {
+ if (e->section()!=Entry::ENUM_SEC)
+ {
+ buildSequenceList(e);
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------
+// Searches the Entry tree for dictionary documentation sections.
+// If found they are stored in the global list.
+static void buildDictionaryList(EntryNav *rootNav)
+{
+ if (!rootNav->name().isEmpty() &&
+ rootNav->section()==Entry::VARIABLE_SEC &&
+ rootNav->type().find("dictionary<")!=-1 // it's a dictionary
+ )
+ {
+ addVariable(rootNav);
+ }
+ if (rootNav->children())
+ {
+ EntryNavListIterator eli(*rootNav->children());
+ EntryNav *e;
+ for (;(e=eli.current());++eli)
+ {
+ if (e->section()!=Entry::ENUM_SEC)
+ {
+ buildDictionaryList(e);
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------
// Searches the Entry tree for Variable documentation sections.
// If found they are stored in their class or in the global list.
@@ -3113,7 +3187,7 @@ static void addInterfaceOrServiceToServiceOrSingleton(
MemberDef *const md = new MemberDef(
fileName, root->startLine, root->startColumn, root->type, rname,
"", "", root->protection, root->virt, root->stat, Member,
- type, 0, root->argList);
+ type, 0, root->argList, root->metaData);
md->setTagInfo(rootNav->tagInfo());
md->setMemberClass(cd);
md->setDocumentation(root->doc,root->docFile,root->docLine);
@@ -3132,6 +3206,8 @@ static void addInterfaceOrServiceToServiceOrSingleton(
md->setDefinition(def);
md->enableCallGraph(root->callGraph);
md->enableCallerGraph(root->callerGraph);
+ md->enableReferencedByRelation(root->referencedByRelation);
+ md->enableReferencesRelation(root->referencesRelation);
Debug::print(Debug::Functions,0,
" Interface Member:\n"
@@ -3300,7 +3376,7 @@ static void addMethodToClass(EntryNav *rootNav,ClassDef *cd,
root->stat && root->relatesType != MemberOf,
root->relates.isEmpty() ? Member :
root->relatesType == MemberOf ? Foreign : Related,
- mtype,root->tArgLists ? root->tArgLists->getLast() : 0,root->argList);
+ mtype,root->tArgLists ? root->tArgLists->getLast() : 0,root->argList, root->metaData);
md->setTagInfo(rootNav->tagInfo());
md->setMemberClass(cd);
md->setDocumentation(root->doc,root->docFile,root->docLine);
@@ -3384,6 +3460,8 @@ static void addMethodToClass(EntryNav *rootNav,ClassDef *cd,
md->setDefinition(def);
md->enableCallGraph(root->callGraph);
md->enableCallerGraph(root->callerGraph);
+ md->enableReferencedByRelation(root->referencedByRelation);
+ md->enableReferencesRelation(root->referencesRelation);
Debug::print(Debug::Functions,0,
" Func Member:\n"
@@ -3651,6 +3729,8 @@ static void buildFunctionList(EntryNav *rootNav)
md->enableCallGraph(md->hasCallGraph() || root->callGraph);
md->enableCallerGraph(md->hasCallerGraph() || root->callerGraph);
+ md->enableReferencedByRelation(md->hasReferencedByRelation() || root->referencedByRelation);
+ md->enableReferencesRelation(md->hasReferencesRelation() || root->referencesRelation);
// merge ingroup specifiers
if (md->getGroupDef()==0 && root->groups->getFirst()!=0)
@@ -3690,7 +3770,7 @@ static void buildFunctionList(EntryNav *rootNav)
root->fileName,root->startLine,root->startColumn,
root->type,name,root->args,root->exception,
root->protection,root->virt,root->stat,Member,
- MemberType_Function,tArgList,root->argList);
+ MemberType_Function,tArgList,root->argList,root->metaData);
md->setTagInfo(rootNav->tagInfo());
md->setLanguage(root->lang);
@@ -3770,6 +3850,8 @@ static void buildFunctionList(EntryNav *rootNav)
md->setDefinition(def);
md->enableCallGraph(root->callGraph);
md->enableCallerGraph(root->callerGraph);
+ md->enableReferencedByRelation(root->referencedByRelation);
+ md->enableReferencesRelation(root->referencesRelation);
//if (root->mGrpId!=-1)
//{
// md->setMemberGroup(memberGroupDict[root->mGrpId]);
@@ -3921,8 +4003,13 @@ static void findFriends()
mmd->enableCallGraph(mmd->hasCallGraph() || fmd->hasCallGraph());
mmd->enableCallerGraph(mmd->hasCallerGraph() || fmd->hasCallerGraph());
+ mmd->enableReferencedByRelation(mmd->hasReferencedByRelation() || fmd->hasReferencedByRelation());
+ mmd->enableReferencesRelation(mmd->hasReferencesRelation() || fmd->hasReferencesRelation());
+
fmd->enableCallGraph(mmd->hasCallGraph() || fmd->hasCallGraph());
fmd->enableCallerGraph(mmd->hasCallerGraph() || fmd->hasCallerGraph());
+ fmd->enableReferencedByRelation(mmd->hasReferencedByRelation() || fmd->hasReferencedByRelation());
+ fmd->enableReferencesRelation(mmd->hasReferencesRelation() || fmd->hasReferencesRelation());
}
}
}
@@ -5322,6 +5409,8 @@ static void addMemberDocs(EntryNav *rootNav,
md->setDefinition(fDecl);
md->enableCallGraph(root->callGraph);
md->enableCallerGraph(root->callerGraph);
+ md->enableReferencedByRelation(root->referencedByRelation);
+ md->enableReferencesRelation(root->referencesRelation);
ClassDef *cd=md->getClassDef();
NamespaceDef *nd=md->getNamespaceDef();
QCString fullName;
@@ -5414,6 +5503,8 @@ static void addMemberDocs(EntryNav *rootNav,
md->enableCallGraph(md->hasCallGraph() || root->callGraph);
md->enableCallerGraph(md->hasCallerGraph() || root->callerGraph);
+ md->enableReferencedByRelation(md->hasReferencedByRelation() || root->referencedByRelation);
+ md->enableReferencesRelation(md->hasReferencesRelation() || root->referencesRelation);
md->mergeMemberSpecifiers(root->spec);
md->addSectionsToDefinition(root->anchors);
@@ -6435,7 +6526,7 @@ static void findMember(EntryNav *rootNav,
funcType,funcName,funcArgs,exceptions,
declMd ? declMd->protection() : root->protection,
root->virt,root->stat,Member,
- mtype,tArgList,root->argList);
+ mtype,tArgList,root->argList,root->metaData);
//printf("new specialized member %s args=`%s'\n",md->name().data(),funcArgs.data());
md->setTagInfo(rootNav->tagInfo());
md->setLanguage(root->lang);
@@ -6446,6 +6537,8 @@ static void findMember(EntryNav *rootNav,
md->setDefinition(funcDecl);
md->enableCallGraph(root->callGraph);
md->enableCallerGraph(root->callerGraph);
+ md->enableReferencedByRelation(root->referencedByRelation);
+ md->enableReferencesRelation(root->referencesRelation);
md->setDocumentation(root->doc,root->docFile,root->docLine);
md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
@@ -6502,7 +6595,7 @@ static void findMember(EntryNav *rootNav,
root->fileName,root->startLine,root->startColumn,
funcType,funcName,funcArgs,exceptions,
root->protection,root->virt,root->stat,Related,
- mtype,tArgList,root->argList);
+ mtype,tArgList,root->argList,root->metaData);
md->setTagInfo(rootNav->tagInfo());
md->setLanguage(root->lang);
md->setId(root->id);
@@ -6511,6 +6604,8 @@ static void findMember(EntryNav *rootNav,
md->setDefinition(funcDecl);
md->enableCallGraph(root->callGraph);
md->enableCallerGraph(root->callerGraph);
+ md->enableReferencedByRelation(root->referencedByRelation);
+ md->enableReferencesRelation(root->referencesRelation);
QCString doc=getOverloadDocs();
doc+="<p>";
doc+=root->doc;
@@ -6640,7 +6735,7 @@ static void findMember(EntryNav *rootNav,
isMemberOf ? Foreign : Related,
mtype,
(root->tArgLists ? root->tArgLists->getLast() : 0),
- funcArgs.isEmpty() ? 0 : root->argList);
+ funcArgs.isEmpty() ? 0 : root->argList,root->metaData);
if (isDefine && mdDefine)
{
@@ -6715,6 +6810,8 @@ static void findMember(EntryNav *rootNav,
md->setDefinition(funcDecl);
md->enableCallGraph(root->callGraph);
md->enableCallerGraph(root->callerGraph);
+ md->enableReferencedByRelation(root->referencedByRelation);
+ md->enableReferencesRelation(root->referencesRelation);
md->setDocumentation(root->doc,root->docFile,root->docLine);
md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
md->setDocsForDefinition(!root->proto);
@@ -6778,7 +6875,7 @@ localObjCMethod:
root->fileName,root->startLine,root->startColumn,
funcType,funcName,funcArgs,exceptions,
root->protection,root->virt,root->stat,Member,
- MemberType_Function,0,root->argList);
+ MemberType_Function,0,root->argList,root->metaData);
md->setTagInfo(rootNav->tagInfo());
md->setLanguage(root->lang);
md->setId(root->id);
@@ -6787,6 +6884,8 @@ localObjCMethod:
md->setDefinition(funcDecl);
md->enableCallGraph(root->callGraph);
md->enableCallerGraph(root->callerGraph);
+ md->enableReferencedByRelation(root->referencedByRelation);
+ md->enableReferencesRelation(root->referencesRelation);
md->setDocumentation(root->doc,root->docFile,root->docLine);
md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
@@ -7114,7 +7213,7 @@ static void findEnums(EntryNav *rootNav)
root->protection,Normal,FALSE,
isMemberOf ? Foreign : isRelated ? Related : Member,
MemberType_Enumeration,
- 0,0);
+ 0,0,root->metaData);
md->setTagInfo(rootNav->tagInfo());
md->setLanguage(root->lang);
md->setId(root->id);
@@ -7129,6 +7228,8 @@ static void findEnums(EntryNav *rootNav)
md->setMemberGroupId(root->mGrpId);
md->enableCallGraph(root->callGraph);
md->enableCallerGraph(root->callerGraph);
+ md->enableReferencedByRelation(root->referencedByRelation);
+ md->enableReferencesRelation(root->referencesRelation);
//printf("%s::setRefItems(%d)\n",md->name().data(),root->sli?root->sli->count():-1);
md->setRefItems(root->sli);
//printf("found enum %s nd=%p\n",md->name().data(),nd);
@@ -7336,7 +7437,7 @@ static void addEnumValuesToEnums(EntryNav *rootNav)
fileName,root->startLine,root->startColumn,
root->type,root->name,root->args,0,
root->protection, Normal,root->stat,Member,
- MemberType_EnumValue,0,0);
+ MemberType_EnumValue,0,0,root->metaData);
if (md->getClassDef()) fmd->setMemberClass(md->getClassDef());
else if (md->getNamespaceDef()) fmd->setNamespace(md->getNamespaceDef());
else if (md->getFileDef()) fmd->setFileDef(md->getFileDef());
@@ -7696,7 +7797,7 @@ static void computeMemberRelations()
// bmcd->name().data(),bmd->name().data(),bmd
// );
if (md!=bmd && bmcd && mcd && bmcd!=mcd &&
- (bmd->virtualness()!=Normal ||
+ (bmd->virtualness()!=Normal || bmd->getLanguage()==SrcLangExt_Python ||
bmcd->compoundType()==ClassDef::Interface ||
bmcd->compoundType()==ClassDef::Protocol
) &&
@@ -8466,7 +8567,7 @@ static void findDefineDocumentation(EntryNav *rootNav)
{
MemberDef *md=new MemberDef(rootNav->tagInfo()->tagName,1,1,
"#define",root->name,root->args,0,
- Public,Normal,FALSE,Member,MemberType_Define,0,0);
+ Public,Normal,FALSE,Member,MemberType_Define,0,0,"");
md->setTagInfo(rootNav->tagInfo());
md->setLanguage(root->lang);
//printf("Searching for `%s' fd=%p\n",filePathName.data(),fd);
@@ -9051,8 +9152,33 @@ static void generateGroupDocs()
//----------------------------------------------------------------------------
// generate module pages
+static void generateNamespaceClassDocs(ClassSDict *d)
+{
+ // for each class in the namespace...
+ ClassSDict::Iterator cli(*d);
+ ClassDef *cd;
+ for ( ; (cd=cli.current()) ; ++cli )
+ {
+ 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",cd->name().data());
+
+ cd->writeDocumentation(*g_outputList);
+ cd->writeMemberList(*g_outputList);
+ }
+ cd->writeDocumentationForInnerClasses(*g_outputList);
+ }
+}
+
static void generateNamespaceDocs()
{
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+
//writeNamespaceIndex(*g_outputList);
NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
@@ -9067,24 +9193,12 @@ static void generateNamespaceDocs()
nd->writeDocumentation(*g_outputList);
}
- // for each class in the namespace...
- ClassSDict::Iterator cli(*nd->getClassSDict());
- ClassDef *cd;
- for ( ; (cd=cli.current()) ; ++cli )
+ generateNamespaceClassDocs(nd->getClassSDict());
+ if (sliceOpt)
{
- 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",cd->name().data());
-
- cd->writeDocumentation(*g_outputList);
- cd->writeMemberList(*g_outputList);
- }
- cd->writeDocumentationForInnerClasses(*g_outputList);
+ generateNamespaceClassDocs(nd->getInterfaceSDict());
+ generateNamespaceClassDocs(nd->getStructSDict());
+ generateNamespaceClassDocs(nd->getExceptionSDict());
}
}
}
@@ -9650,7 +9764,7 @@ int readDir(QFileInfo *fi,
{
fn = new FileName(cfi->absFilePath().utf8(),name);
fn->append(fd);
- if (fnList) fnList->inSort(fn);
+ if (fnList) fnList->append(fn);
fnDict->insert(name,fn);
}
}
@@ -9749,7 +9863,7 @@ int readFileOrDirectory(const char *s,
{
fn = new FileName(filePath,name);
fn->append(fd);
- if (fnList) fnList->inSort(fn);
+ if (fnList) fnList->append(fn);
fnDict->insert(name,fn);
}
}
@@ -9888,7 +10002,7 @@ static void escapeAliases()
while ((in=value.find("^^",p))!=-1)
{
newValue+=value.mid(p,in-p);
- newValue+="\n";
+ newValue+="@_linebr";
p=in+2;
}
newValue+=value.mid(p,value.length()-p);
@@ -10028,6 +10142,9 @@ static void usage(const char *name)
msg(" RTF: %s -e rtf extensionsFile\n\n",name);
msg("7) Use doxygen to compare the used configuration file with the template configuration file\n");
msg(" %s -x [configFile]\n\n",name);
+ msg("8) Use doxygen to show a list of build in emoji.\n");
+ msg(" %s -f emoji outputFileName\n\n",name);
+ msg(" If - is used for outputFileName doxygen will write to standard output.\n\n");
msg("If -s is specified the comments of the configuration items in the config file will be omitted.\n");
msg("If configName is omitted `Doxyfile' will be used as a default.\n\n");
msg("-v print version string\n");
@@ -10228,6 +10345,7 @@ void readConfiguration(int argc, char **argv)
const char *layoutName=0;
const char *debugLabel;
const char *formatName;
+ const char *listName;
bool genConfig=FALSE;
bool shortList=FALSE;
bool diffList=FALSE;
@@ -10305,6 +10423,34 @@ void readConfiguration(int argc, char **argv)
cleanUpDoxygen();
exit(1);
break;
+ case 'f':
+ listName=getArg(argc,argv,optind);
+ if (!listName)
+ {
+ err("option \"-f\" is missing list specifier.\n");
+ cleanUpDoxygen();
+ exit(1);
+ }
+ if (qstricmp(listName,"emoji")==0)
+ {
+ if (optind+1>=argc)
+ {
+ err("option \"-f emoji\" is missing an output file name\n");
+ cleanUpDoxygen();
+ exit(1);
+ }
+ QFile f;
+ if (openOutputFile(argv[optind+1],f))
+ {
+ EmojiEntityMapper::instance()->writeEmojiFile(f);
+ }
+ cleanUpDoxygen();
+ exit(0);
+ }
+ err("option \"-f\" has invalid list specifier.\n");
+ cleanUpDoxygen();
+ exit(1);
+ break;
case 'w':
formatName=getArg(argc,argv,optind);
if (!formatName)
@@ -10679,6 +10825,10 @@ static void stopDoxygen(int)
{
thisDir.remove(Doxygen::objDBFileName);
}
+ if (!Doxygen::filterDBFileName.isEmpty())
+ {
+ thisDir.remove(Doxygen::filterDBFileName);
+ }
killpg(0,SIGINT);
exit(1);
}
@@ -10779,6 +10929,10 @@ static void exitDoxygen()
{
thisDir.remove(Doxygen::objDBFileName);
}
+ if (!Doxygen::filterDBFileName.isEmpty())
+ {
+ thisDir.remove(Doxygen::filterDBFileName);
+ }
}
}
@@ -10954,6 +11108,7 @@ void searchInputFiles()
}
s=inputList.next();
}
+ Doxygen::inputNameList->sort();
delete killDict;
g_s.end();
}
@@ -11018,6 +11173,8 @@ void parseInput()
Doxygen::objDBFileName.prepend(outputDirectory+"/");
Doxygen::entryDBFileName.sprintf("doxygen_entrydb_%d.tmp",pid);
Doxygen::entryDBFileName.prepend(outputDirectory+"/");
+ Doxygen::filterDBFileName.sprintf("doxygen_filterdb_%d.tmp",pid);
+ Doxygen::filterDBFileName.prepend(outputDirectory+"/");
if (Doxygen::symbolStorage->open(Doxygen::objDBFileName)==-1)
{
@@ -11264,6 +11421,17 @@ void parseInput()
buildTypedefList(rootNav);
g_s.end();
+ if (Config_getBool(OPTIMIZE_OUTPUT_SLICE))
+ {
+ g_s.begin("Searching for documented sequences...\n");
+ buildSequenceList(rootNav);
+ g_s.end();
+
+ g_s.begin("Searching for documented dictionaries...\n");
+ buildDictionaryList(rootNav);
+ g_s.end();
+ }
+
g_s.begin("Searching for members imported via using declarations...\n");
// this should be after buildTypedefList in order to properly import
// used typedefs
@@ -11521,13 +11689,11 @@ void generateOutput()
g_outputList->add(new LatexGenerator);
LatexGenerator::init();
}
-#if 1
if (generateDocbook)
{
g_outputList->add(new DocbookGenerator);
DocbookGenerator::init();
}
-#endif
if (generateMan)
{
g_outputList->add(new ManGenerator);
@@ -11706,15 +11872,6 @@ void generateOutput()
g_s.end();
}
-#if 0
- if (generateDocbook)
- {
- g_s.begin("Generating Docbook output...\n");
- generateDocbook_v1();
- g_s.end();
- }
-#endif
-
if (Config_getBool(GENERATE_AUTOGEN_DEF))
{
g_s.begin("Generating AutoGen DEF output...\n");
@@ -11867,6 +12024,7 @@ void generateOutput()
Doxygen::symbolStorage->close();
QDir thisDir;
thisDir.remove(Doxygen::objDBFileName);
+ thisDir.remove(Doxygen::filterDBFileName);
Config::deinit();
QTextCodec::deleteAllCodecs();
delete Doxygen::symbolMap;
diff --git a/src/doxygen.h b/src/doxygen.h
index 7bd05a4..4ff8a56 100644
--- a/src/doxygen.h
+++ b/src/doxygen.h
@@ -140,6 +140,7 @@ class Doxygen
static Store *symbolStorage;
static QCString objDBFileName;
static QCString entryDBFileName;
+ static QCString filterDBFileName;
static CiteDict *citeDict;
static bool gatherDefines;
static bool userComments;
diff --git a/src/emoji.cpp b/src/emoji.cpp
new file mode 100644
index 0000000..f10ebc5
--- /dev/null
+++ b/src/emoji.cpp
@@ -0,0 +1,3187 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1997-2018 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+#include "emoji.h"
+#include "message.h"
+#include "ftextstream.h"
+#include "util.h"
+
+/* to generate the content of this table see the documentation at the end of this file */
+static struct emojiEntityInfo
+{
+ const char *githubName;
+ const char *unicodeName;
+ const char *code;
+} g_emojiEntities[] =
+{
+ {":+1:", ":thumbs up:", "&#x1f44d;"},
+ {":-1:", ":thumbs down:", "&#x1f44e;"},
+ {":100:", ":hundred points:", "&#x1f4af;"},
+ {":1234:", ":input numbers:", "&#x1f522;"},
+ {":1st_place_medal:", ":1st place medal:", "&#x1f947;"},
+ {":2nd_place_medal:", ":2nd place medal:", "&#x1f948;"},
+ {":3rd_place_medal:", ":3rd place medal:", "&#x1f949;"},
+ {":8ball:", ":pool 8 ball:", "&#x1f3b1;"},
+ {":a:", ":a button (blood type):", "&#x1f170;"},
+ {":ab:", ":ab button (blood type):", "&#x1f18e;"},
+ {":abc:", ":input latin letters:", "&#x1f524;"},
+ {":abcd:", ":input latin lowercase:", "&#x1f521;"},
+ {":accept:", ":japanese \"acceptable\" button:", "&#x1f251;"},
+ {":aerial_tramway:", ":aerial tramway:", "&#x1f6a1;"},
+ {":afghanistan:", ":flag afghanistan:", "&#x1f1e6;&#x1f1eb;"},
+ {":airplane:", ":airplane:", "&#x2708;"},
+ {":aland_islands:", ":flag Ã…land islands:", "&#x1f1e6;&#x1f1fd;"},
+ {":alarm_clock:", ":alarm clock:", "&#x23f0;"},
+ {":albania:", ":flag albania:", "&#x1f1e6;&#x1f1f1;"},
+ {":alembic:", ":alembic:", "&#x2697;"},
+ {":algeria:", ":flag algeria:", "&#x1f1e9;&#x1f1ff;"},
+ {":alien:", ":alien:", "&#x1f47d;"},
+ {":ambulance:", ":ambulance:", "&#x1f691;"},
+ {":american_samoa:", ":flag american samoa:", "&#x1f1e6;&#x1f1f8;"},
+ {":amphora:", ":amphora:", "&#x1f3fa;"},
+ {":anchor:", ":anchor:", "&#x2693;"},
+ {":andorra:", ":flag andorra:", "&#x1f1e6;&#x1f1e9;"},
+ {":angel:", ":baby angel:", "&#x1f47c;"},
+ {":anger:", ":anger symbol:", "&#x1f4a2;"},
+ {":angola:", ":flag angola:", "&#x1f1e6;&#x1f1f4;"},
+ {":angry:", ":angry face:", "&#x1f620;"},
+ {":anguilla:", ":flag anguilla:", "&#x1f1e6;&#x1f1ee;"},
+ {":anguished:", ":anguished face:", "&#x1f627;"},
+ {":ant:", ":ant:", "&#x1f41c;"},
+ {":antarctica:", ":flag antarctica:", "&#x1f1e6;&#x1f1f6;"},
+ {":antigua_barbuda:", ":flag antigua & barbuda:", "&#x1f1e6;&#x1f1ec;"},
+ {":apple:", ":red apple:", "&#x1f34e;"},
+ {":aquarius:", ":aquarius:", "&#x2652;"},
+ {":argentina:", ":flag argentina:", "&#x1f1e6;&#x1f1f7;"},
+ {":aries:", ":aries:", "&#x2648;"},
+ {":armenia:", ":flag armenia:", "&#x1f1e6;&#x1f1f2;"},
+ {":arrow_backward:", ":reverse button:", "&#x25c0;"},
+ {":arrow_double_down:", ":fast down button:", "&#x23ec;"},
+ {":arrow_double_up:", ":fast up button:", "&#x23eb;"},
+ {":arrow_down:", ":down arrow:", "&#x2b07;"},
+ {":arrow_down_small:", ":downwards button:", "&#x1f53d;"},
+ {":arrow_forward:", ":play button:", "&#x25b6;"},
+ {":arrow_heading_down:", ":right arrow curving down:", "&#x2935;"},
+ {":arrow_heading_up:", ":right arrow curving up:", "&#x2934;"},
+ {":arrow_left:", ":left arrow:", "&#x2b05;"},
+ {":arrow_lower_left:", ":down-left arrow:", "&#x2199;"},
+ {":arrow_lower_right:", ":down-right arrow:", "&#x2198;"},
+ {":arrow_right:", ":right arrow:", "&#x27a1;"},
+ {":arrow_right_hook:", ":left arrow curving right:", "&#x21aa;"},
+ {":arrow_up:", ":up arrow:", "&#x2b06;"},
+ {":arrow_up_down:", ":up-down arrow:", "&#x2195;"},
+ {":arrow_up_small:", ":upwards button:", "&#x1f53c;"},
+ {":arrow_upper_left:", ":up-left arrow:", "&#x2196;"},
+ {":arrow_upper_right:", ":up-right arrow:", "&#x2197;"},
+ {":arrows_clockwise:", ":clockwise vertical arrows:", "&#x1f503;"},
+ {":arrows_counterclockwise:", ":counterclockwise arrows button:", "&#x1f504;"},
+ {":art:", ":artist palette:", "&#x1f3a8;"},
+ {":articulated_lorry:", ":articulated lorry:", "&#x1f69b;"},
+ {":artificial_satellite:", ":satellite:", "&#x1f6f0;"},
+ {":aruba:", ":flag aruba:", "&#x1f1e6;&#x1f1fc;"},
+ {":asterisk:", ":keycap *:", "&#x002a;&#xfe0f;&#x20e3;"},
+ {":astonished:", ":astonished face:", "&#x1f632;"},
+ {":athletic_shoe:", ":running shoe:", "&#x1f45f;"},
+ {":atm:", ":atm sign:", "&#x1f3e7;"},
+ {":atom_symbol:", ":atom symbol:", "&#x269b;"},
+ {":australia:", ":flag australia:", "&#x1f1e6;&#x1f1fa;"},
+ {":austria:", ":flag austria:", "&#x1f1e6;&#x1f1f9;"},
+ {":avocado:", ":avocado:", "&#x1f951;"},
+ {":azerbaijan:", ":flag azerbaijan:", "&#x1f1e6;&#x1f1ff;"},
+ {":b:", ":b button (blood type):", "&#x1f171;"},
+ {":baby:", ":baby:", "&#x1f476;"},
+ {":baby_bottle:", ":baby bottle:", "&#x1f37c;"},
+ {":baby_chick:", ":baby chick:", "&#x1f424;"},
+ {":baby_symbol:", ":baby symbol:", "&#x1f6bc;"},
+ {":back:", ":back arrow:", "&#x1f519;"},
+ {":bacon:", ":bacon:", "&#x1f953;"},
+ {":badminton:", ":badminton:", "&#x1f3f8;"},
+ {":baggage_claim:", ":baggage claim:", "&#x1f6c4;"},
+ {":baguette_bread:", ":baguette bread:", "&#x1f956;"},
+ {":bahamas:", ":flag bahamas:", "&#x1f1e7;&#x1f1f8;"},
+ {":bahrain:", ":flag bahrain:", "&#x1f1e7;&#x1f1ed;"},
+ {":balance_scale:", ":balance scale:", "&#x2696;"},
+ {":balloon:", ":balloon:", "&#x1f388;"},
+ {":ballot_box:", ":ballot box with ballot:", "&#x1f5f3;"},
+ {":ballot_box_with_check:", ":ballot box with check:", "&#x2611;"},
+ {":bamboo:", ":pine decoration:", "&#x1f38d;"},
+ {":banana:", ":banana:", "&#x1f34c;"},
+ {":bangbang:", ":double exclamation mark:", "&#x203c;"},
+ {":bangladesh:", ":flag bangladesh:", "&#x1f1e7;&#x1f1e9;"},
+ {":bank:", ":bank:", "&#x1f3e6;"},
+ {":bar_chart:", ":bar chart:", "&#x1f4ca;"},
+ {":barbados:", ":flag barbados:", "&#x1f1e7;&#x1f1e7;"},
+ {":barber:", ":barber pole:", "&#x1f488;"},
+ {":baseball:", ":baseball:", "&#x26be;"},
+ {":basketball:", ":basketball:", "&#x1f3c0;"},
+ {":basketball_man:", ":person bouncing ball:", "&#x26f9;"},
+ {":basketball_woman:", ":woman bouncing ball:", "&#x26f9;&#xfe0f;&#x200d;&#x2640;&#xfe0f;"},
+ {":bat:", ":bat:", "&#x1f987;"},
+ {":bath:", ":person taking bath:", "&#x1f6c0;"},
+ {":bathtub:", ":bathtub:", "&#x1f6c1;"},
+ {":battery:", ":battery:", "&#x1f50b;"},
+ {":beach_umbrella:", ":beach with umbrella:", "&#x1f3d6;"},
+ {":bear:", ":bear face:", "&#x1f43b;"},
+ {":bed:", ":bed:", "&#x1f6cf;"},
+ {":bee:", ":honeybee:", "&#x1f41d;"},
+ {":beer:", ":beer mug:", "&#x1f37a;"},
+ {":beers:", ":clinking beer mugs:", "&#x1f37b;"},
+ {":beetle:", ":lady beetle:", "&#x1f41e;"},
+ {":beginner:", ":japanese symbol for beginner:", "&#x1f530;"},
+ {":belarus:", ":flag belarus:", "&#x1f1e7;&#x1f1fe;"},
+ {":belgium:", ":flag belgium:", "&#x1f1e7;&#x1f1ea;"},
+ {":belize:", ":flag belize:", "&#x1f1e7;&#x1f1ff;"},
+ {":bell:", ":bell:", "&#x1f514;"},
+ {":bellhop_bell:", ":bellhop bell:", "&#x1f6ce;"},
+ {":benin:", ":flag benin:", "&#x1f1e7;&#x1f1ef;"},
+ {":bento:", ":bento box:", "&#x1f371;"},
+ {":bermuda:", ":flag bermuda:", "&#x1f1e7;&#x1f1f2;"},
+ {":bhutan:", ":flag bhutan:", "&#x1f1e7;&#x1f1f9;"},
+ {":bicyclist:", ":person biking:", "&#x1f6b4;"},
+ {":bike:", ":bicycle:", "&#x1f6b2;"},
+ {":biking_man:", ":person biking:", "&#x1f6b4;"},
+ {":biking_woman:", ":woman biking:", "&#x1f6b4;&#x200d;&#x2640;&#xfe0f;"},
+ {":bikini:", ":bikini:", "&#x1f459;"},
+ {":biohazard:", ":biohazard:", "&#x2623;"},
+ {":bird:", ":bird:", "&#x1f426;"},
+ {":birthday:", ":birthday cake:", "&#x1f382;"},
+ {":black_circle:", ":black circle:", "&#x26ab;"},
+ {":black_flag:", ":black flag:", "&#x1f3f4;"},
+ {":black_heart:", ":black heart:", "&#x1f5a4;"},
+ {":black_joker:", ":joker:", "&#x1f0cf;"},
+ {":black_large_square:", ":black large square:", "&#x2b1b;"},
+ {":black_medium_small_square:", ":black medium-small square:", "&#x25fe;"},
+ {":black_medium_square:", ":black medium square:", "&#x25fc;"},
+ {":black_nib:", ":black nib:", "&#x2712;"},
+ {":black_small_square:", ":black small square:", "&#x25aa;"},
+ {":black_square_button:", ":black square button:", "&#x1f532;"},
+ {":blonde_man:", ":person blond hair:", "&#x1f471;"},
+ {":blonde_woman:", ":woman blond hair:", "&#x1f471;&#x200d;&#x2640;&#xfe0f;"},
+ {":blossom:", ":blossom:", "&#x1f33c;"},
+ {":blowfish:", ":blowfish:", "&#x1f421;"},
+ {":blue_book:", ":blue book:", "&#x1f4d8;"},
+ {":blue_car:", ":sport utility vehicle:", "&#x1f699;"},
+ {":blue_heart:", ":blue heart:", "&#x1f499;"},
+ {":blush:", ":smiling face with smiling eyes:", "&#x1f60a;"},
+ {":boar:", ":boar:", "&#x1f417;"},
+ {":boat:", ":sailboat:", "&#x26f5;"},
+ {":bolivia:", ":flag bolivia:", "&#x1f1e7;&#x1f1f4;"},
+ {":bomb:", ":bomb:", "&#x1f4a3;"},
+ {":book:", ":open book:", "&#x1f4d6;"},
+ {":bookmark:", ":bookmark:", "&#x1f516;"},
+ {":bookmark_tabs:", ":bookmark tabs:", "&#x1f4d1;"},
+ {":books:", ":books:", "&#x1f4da;"},
+ {":boom:", ":collision:", "&#x1f4a5;"},
+ {":boot:", ":woman's boot:", "&#x1f462;"},
+ {":bosnia_herzegovina:", ":flag bosnia & herzegovina:", "&#x1f1e7;&#x1f1e6;"},
+ {":botswana:", ":flag botswana:", "&#x1f1e7;&#x1f1fc;"},
+ {":bouquet:", ":bouquet:", "&#x1f490;"},
+ {":bow:", ":person bowing:", "&#x1f647;"},
+ {":bow_and_arrow:", ":bow and arrow:", "&#x1f3f9;"},
+ {":bowing_man:", ":person bowing:", "&#x1f647;"},
+ {":bowing_woman:", ":woman bowing:", "&#x1f647;&#x200d;&#x2640;&#xfe0f;"},
+ {":bowling:", ":bowling:", "&#x1f3b3;"},
+ {":boxing_glove:", ":boxing glove:", "&#x1f94a;"},
+ {":boy:", ":boy:", "&#x1f466;"},
+ {":brazil:", ":flag brazil:", "&#x1f1e7;&#x1f1f7;"},
+ {":bread:", ":bread:", "&#x1f35e;"},
+ {":bride_with_veil:", ":bride with veil:", "&#x1f470;"},
+ {":bridge_at_night:", ":bridge at night:", "&#x1f309;"},
+ {":briefcase:", ":briefcase:", "&#x1f4bc;"},
+ {":british_indian_ocean_territory:", ":flag british indian ocean territory:", "&#x1f1ee;&#x1f1f4;"},
+ {":british_virgin_islands:", ":flag british virgin islands:", "&#x1f1fb;&#x1f1ec;"},
+ {":broken_heart:", ":broken heart:", "&#x1f494;"},
+ {":brunei:", ":flag brunei:", "&#x1f1e7;&#x1f1f3;"},
+ {":bug:", ":bug:", "&#x1f41b;"},
+ {":building_construction:", ":building construction:", "&#x1f3d7;"},
+ {":bulb:", ":light bulb:", "&#x1f4a1;"},
+ {":bulgaria:", ":flag bulgaria:", "&#x1f1e7;&#x1f1ec;"},
+ {":bullettrain_front:", ":bullet train:", "&#x1f685;"},
+ {":bullettrain_side:", ":high-speed train:", "&#x1f684;"},
+ {":burkina_faso:", ":flag burkina faso:", "&#x1f1e7;&#x1f1eb;"},
+ {":burrito:", ":burrito:", "&#x1f32f;"},
+ {":burundi:", ":flag burundi:", "&#x1f1e7;&#x1f1ee;"},
+ {":bus:", ":bus:", "&#x1f68c;"},
+ {":business_suit_levitating:", ":man in suit levitating:", "&#x1f574;"},
+ {":busstop:", ":bus stop:", "&#x1f68f;"},
+ {":bust_in_silhouette:", ":bust in silhouette:", "&#x1f464;"},
+ {":busts_in_silhouette:", ":busts in silhouette:", "&#x1f465;"},
+ {":butterfly:", ":butterfly:", "&#x1f98b;"},
+ {":cactus:", ":cactus:", "&#x1f335;"},
+ {":cake:", ":shortcake:", "&#x1f370;"},
+ {":calendar:", ":tear-off calendar:", "&#x1f4c6;"},
+ {":call_me_hand:", ":call me hand:", "&#x1f919;"},
+ {":calling:", ":mobile phone with arrow:", "&#x1f4f2;"},
+ {":cambodia:", ":flag cambodia:", "&#x1f1f0;&#x1f1ed;"},
+ {":camel:", ":two-hump camel:", "&#x1f42b;"},
+ {":camera:", ":camera:", "&#x1f4f7;"},
+ {":camera_flash:", ":camera with flash:", "&#x1f4f8;"},
+ {":cameroon:", ":flag cameroon:", "&#x1f1e8;&#x1f1f2;"},
+ {":camping:", ":camping:", "&#x1f3d5;"},
+ {":canada:", ":flag canada:", "&#x1f1e8;&#x1f1e6;"},
+ {":canary_islands:", ":flag canary islands:", "&#x1f1ee;&#x1f1e8;"},
+ {":cancer:", ":cancer:", "&#x264b;"},
+ {":candle:", ":candle:", "&#x1f56f;"},
+ {":candy:", ":candy:", "&#x1f36c;"},
+ {":canoe:", ":canoe:", "&#x1f6f6;"},
+ {":cape_verde:", ":flag cape verde:", "&#x1f1e8;&#x1f1fb;"},
+ {":capital_abcd:", ":input latin uppercase:", "&#x1f520;"},
+ {":capricorn:", ":capricorn:", "&#x2651;"},
+ {":car:", ":automobile:", "&#x1f697;"},
+ {":card_file_box:", ":card file box:", "&#x1f5c3;"},
+ {":card_index:", ":card index:", "&#x1f4c7;"},
+ {":card_index_dividers:", ":card index dividers:", "&#x1f5c2;"},
+ {":caribbean_netherlands:", ":flag caribbean netherlands:", "&#x1f1e7;&#x1f1f6;"},
+ {":carousel_horse:", ":carousel horse:", "&#x1f3a0;"},
+ {":carrot:", ":carrot:", "&#x1f955;"},
+ {":cat:", ":cat face:", "&#x1f431;"},
+ {":cat2:", ":cat:", "&#x1f408;"},
+ {":cayman_islands:", ":flag cayman islands:", "&#x1f1f0;&#x1f1fe;"},
+ {":cd:", ":optical disk:", "&#x1f4bf;"},
+ {":central_african_republic:", ":flag central african republic:", "&#x1f1e8;&#x1f1eb;"},
+ {":chad:", ":flag chad:", "&#x1f1f9;&#x1f1e9;"},
+ {":chains:", ":chains:", "&#x26d3;"},
+ {":champagne:", ":bottle with popping cork:", "&#x1f37e;"},
+ {":chart:", ":chart increasing with yen:", "&#x1f4b9;"},
+ {":chart_with_downwards_trend:", ":chart decreasing:", "&#x1f4c9;"},
+ {":chart_with_upwards_trend:", ":chart increasing:", "&#x1f4c8;"},
+ {":checkered_flag:", ":chequered flag:", "&#x1f3c1;"},
+ {":cheese:", ":cheese wedge:", "&#x1f9c0;"},
+ {":cherries:", ":cherries:", "&#x1f352;"},
+ {":cherry_blossom:", ":cherry blossom:", "&#x1f338;"},
+ {":chestnut:", ":chestnut:", "&#x1f330;"},
+ {":chicken:", ":chicken:", "&#x1f414;"},
+ {":children_crossing:", ":children crossing:", "&#x1f6b8;"},
+ {":chile:", ":flag chile:", "&#x1f1e8;&#x1f1f1;"},
+ {":chipmunk:", ":chipmunk:", "&#x1f43f;"},
+ {":chocolate_bar:", ":chocolate bar:", "&#x1f36b;"},
+ {":christmas_island:", ":flag christmas island:", "&#x1f1e8;&#x1f1fd;"},
+ {":christmas_tree:", ":christmas tree:", "&#x1f384;"},
+ {":church:", ":church:", "&#x26ea;"},
+ {":cinema:", ":cinema:", "&#x1f3a6;"},
+ {":circus_tent:", ":circus tent:", "&#x1f3aa;"},
+ {":city_sunrise:", ":sunset:", "&#x1f307;"},
+ {":city_sunset:", ":cityscape at dusk:", "&#x1f306;"},
+ {":cityscape:", ":cityscape:", "&#x1f3d9;"},
+ {":cl:", ":cl button:", "&#x1f191;"},
+ {":clamp:", ":clamp:", "&#x1f5dc;"},
+ {":clap:", ":clapping hands:", "&#x1f44f;"},
+ {":clapper:", ":clapper board:", "&#x1f3ac;"},
+ {":classical_building:", ":classical building:", "&#x1f3db;"},
+ {":clinking_glasses:", ":clinking glasses:", "&#x1f942;"},
+ {":clipboard:", ":clipboard:", "&#x1f4cb;"},
+ {":clock1:", ":one o'clock:", "&#x1f550;"},
+ {":clock10:", ":ten o'clock:", "&#x1f559;"},
+ {":clock1030:", ":ten-thirty:", "&#x1f565;"},
+ {":clock11:", ":eleven o'clock:", "&#x1f55a;"},
+ {":clock1130:", ":eleven-thirty:", "&#x1f566;"},
+ {":clock12:", ":twelve o'clock:", "&#x1f55b;"},
+ {":clock1230:", ":twelve-thirty:", "&#x1f567;"},
+ {":clock130:", ":one-thirty:", "&#x1f55c;"},
+ {":clock2:", ":two o'clock:", "&#x1f551;"},
+ {":clock230:", ":two-thirty:", "&#x1f55d;"},
+ {":clock3:", ":three o'clock:", "&#x1f552;"},
+ {":clock330:", ":three-thirty:", "&#x1f55e;"},
+ {":clock4:", ":four o'clock:", "&#x1f553;"},
+ {":clock430:", ":four-thirty:", "&#x1f55f;"},
+ {":clock5:", ":five o'clock:", "&#x1f554;"},
+ {":clock530:", ":five-thirty:", "&#x1f560;"},
+ {":clock6:", ":six o'clock:", "&#x1f555;"},
+ {":clock630:", ":six-thirty:", "&#x1f561;"},
+ {":clock7:", ":seven o'clock:", "&#x1f556;"},
+ {":clock730:", ":seven-thirty:", "&#x1f562;"},
+ {":clock8:", ":eight o'clock:", "&#x1f557;"},
+ {":clock830:", ":eight-thirty:", "&#x1f563;"},
+ {":clock9:", ":nine o'clock:", "&#x1f558;"},
+ {":clock930:", ":nine-thirty:", "&#x1f564;"},
+ {":closed_book:", ":closed book:", "&#x1f4d5;"},
+ {":closed_lock_with_key:", ":locked with key:", "&#x1f510;"},
+ {":closed_umbrella:", ":closed umbrella:", "&#x1f302;"},
+ {":cloud:", ":cloud:", "&#x2601;"},
+ {":cloud_with_lightning:", ":cloud with lightning:", "&#x1f329;"},
+ {":cloud_with_lightning_and_rain:", ":cloud with lightning and rain:", "&#x26c8;"},
+ {":cloud_with_rain:", ":cloud with rain:", "&#x1f327;"},
+ {":cloud_with_snow:", ":cloud with snow:", "&#x1f328;"},
+ {":clown_face:", ":clown face:", "&#x1f921;"},
+ {":clubs:", ":club suit:", "&#x2663;"},
+ {":cn:", ":flag china:", "&#x1f1e8;&#x1f1f3;"},
+ {":cocktail:", ":cocktail glass:", "&#x1f378;"},
+ {":cocos_islands:", ":flag cocos (keeling) islands:", "&#x1f1e8;&#x1f1e8;"},
+ {":coffee:", ":hot beverage:", "&#x2615;"},
+ {":coffin:", ":coffin:", "&#x26b0;"},
+ {":cold_sweat:", ":anxious face with sweat:", "&#x1f630;"},
+ {":collision:", ":collision:", "&#x1f4a5;"},
+ {":colombia:", ":flag colombia:", "&#x1f1e8;&#x1f1f4;"},
+ {":comet:", ":comet:", "&#x2604;"},
+ {":comoros:", ":flag comoros:", "&#x1f1f0;&#x1f1f2;"},
+ {":computer:", ":laptop computer:", "&#x1f4bb;"},
+ {":computer_mouse:", ":computer mouse:", "&#x1f5b1;"},
+ {":confetti_ball:", ":confetti ball:", "&#x1f38a;"},
+ {":confounded:", ":confounded face:", "&#x1f616;"},
+ {":confused:", ":confused face:", "&#x1f615;"},
+ {":congo_brazzaville:", ":flag congo - brazzaville:", "&#x1f1e8;&#x1f1ec;"},
+ {":congo_kinshasa:", ":flag congo - kinshasa:", "&#x1f1e8;&#x1f1e9;"},
+ {":congratulations:", ":japanese \"congratulations\" button:", "&#x3297;"},
+ {":construction:", ":construction:", "&#x1f6a7;"},
+ {":construction_worker:", ":construction worker:", "&#x1f477;"},
+ {":construction_worker_man:", ":construction worker:", "&#x1f477;"},
+ {":construction_worker_woman:", ":woman construction worker:", "&#x1f477;&#x200d;&#x2640;&#xfe0f;"},
+ {":control_knobs:", ":control knobs:", "&#x1f39b;"},
+ {":convenience_store:", ":convenience store:", "&#x1f3ea;"},
+ {":cook_islands:", ":flag cook islands:", "&#x1f1e8;&#x1f1f0;"},
+ {":cookie:", ":cookie:", "&#x1f36a;"},
+ {":cool:", ":cool button:", "&#x1f192;"},
+ {":cop:", ":police officer:", "&#x1f46e;"},
+ {":copyright:", ":copyright:", "&#x00a9;"},
+ {":corn:", ":ear of corn:", "&#x1f33d;"},
+ {":costa_rica:", ":flag costa rica:", "&#x1f1e8;&#x1f1f7;"},
+ {":cote_divoire:", ":flag côte d'ivoire:", "&#x1f1e8;&#x1f1ee;"},
+ {":couch_and_lamp:", ":couch and lamp:", "&#x1f6cb;"},
+ {":couple:", ":man and woman holding hands:", "&#x1f46b;"},
+ {":couple_with_heart:", ":couple with heart:", "&#x1f491;"},
+ {":couple_with_heart_man_man:", ":kiss man, man:", "&#x1f468;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f468;"},
+ {":couple_with_heart_woman_man:", ":couple with heart:", "&#x1f491;"},
+ {":couple_with_heart_woman_woman:", ":kiss woman, woman:", "&#x1f469;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f469;"},
+ {":couplekiss_man_man:", ":kiss man, man:", "&#x1f468;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f468;"},
+ {":couplekiss_man_woman:", ":kiss:", "&#x1f48f;"},
+ {":couplekiss_woman_woman:", ":kiss woman, woman:", "&#x1f469;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f469;"},
+ {":cow:", ":cow face:", "&#x1f42e;"},
+ {":cow2:", ":cow:", "&#x1f404;"},
+ {":cowboy_hat_face:", ":cowboy hat face:", "&#x1f920;"},
+ {":crab:", ":crab:", "&#x1f980;"},
+ {":crayon:", ":crayon:", "&#x1f58d;"},
+ {":credit_card:", ":credit card:", "&#x1f4b3;"},
+ {":crescent_moon:", ":crescent moon:", "&#x1f319;"},
+ {":cricket:", ":cricket game:", "&#x1f3cf;"},
+ {":croatia:", ":flag croatia:", "&#x1f1ed;&#x1f1f7;"},
+ {":crocodile:", ":crocodile:", "&#x1f40a;"},
+ {":croissant:", ":croissant:", "&#x1f950;"},
+ {":crossed_fingers:", ":crossed fingers:", "&#x1f91e;"},
+ {":crossed_flags:", ":crossed flags:", "&#x1f38c;"},
+ {":crossed_swords:", ":crossed swords:", "&#x2694;"},
+ {":crown:", ":crown:", "&#x1f451;"},
+ {":cry:", ":crying face:", "&#x1f622;"},
+ {":crying_cat_face:", ":crying cat face:", "&#x1f63f;"},
+ {":crystal_ball:", ":crystal ball:", "&#x1f52e;"},
+ {":cuba:", ":flag cuba:", "&#x1f1e8;&#x1f1fa;"},
+ {":cucumber:", ":cucumber:", "&#x1f952;"},
+ {":cupid:", ":heart with arrow:", "&#x1f498;"},
+ {":curacao:", ":flag curaçao:", "&#x1f1e8;&#x1f1fc;"},
+ {":curly_loop:", ":curly loop:", "&#x27b0;"},
+ {":currency_exchange:", ":currency exchange:", "&#x1f4b1;"},
+ {":curry:", ":curry rice:", "&#x1f35b;"},
+ {":custard:", ":custard:", "&#x1f36e;"},
+ {":customs:", ":customs:", "&#x1f6c3;"},
+ {":cyclone:", ":cyclone:", "&#x1f300;"},
+ {":cyprus:", ":flag cyprus:", "&#x1f1e8;&#x1f1fe;"},
+ {":czech_republic:", ":flag czechia:", "&#x1f1e8;&#x1f1ff;"},
+ {":dagger:", ":dagger:", "&#x1f5e1;"},
+ {":dancer:", ":woman dancing:", "&#x1f483;"},
+ {":dancers:", ":people with bunny ears:", "&#x1f46f;"},
+ {":dancing_men:", ":men with bunny ears:", "&#x1f46f;&#x200d;&#x2642;&#xfe0f;"},
+ {":dancing_women:", ":people with bunny ears:", "&#x1f46f;"},
+ {":dango:", ":dango:", "&#x1f361;"},
+ {":dark_sunglasses:", ":sunglasses:", "&#x1f576;"},
+ {":dart:", ":direct hit:", "&#x1f3af;"},
+ {":dash:", ":dashing away:", "&#x1f4a8;"},
+ {":date:", ":calendar:", "&#x1f4c5;"},
+ {":de:", ":flag germany:", "&#x1f1e9;&#x1f1ea;"},
+ {":deciduous_tree:", ":deciduous tree:", "&#x1f333;"},
+ {":deer:", ":deer:", "&#x1f98c;"},
+ {":denmark:", ":flag denmark:", "&#x1f1e9;&#x1f1f0;"},
+ {":department_store:", ":department store:", "&#x1f3ec;"},
+ {":derelict_house:", ":derelict house:", "&#x1f3da;"},
+ {":desert:", ":desert:", "&#x1f3dc;"},
+ {":desert_island:", ":desert island:", "&#x1f3dd;"},
+ {":desktop_computer:", ":desktop computer:", "&#x1f5a5;"},
+ {":detective:", ":detective:", "&#x1f575;"},
+ {":diamond_shape_with_a_dot_inside:", ":diamond with a dot:", "&#x1f4a0;"},
+ {":diamonds:", ":diamond suit:", "&#x2666;"},
+ {":disappointed:", ":disappointed face:", "&#x1f61e;"},
+ {":disappointed_relieved:", ":sad but relieved face:", "&#x1f625;"},
+ {":dizzy:", ":dizzy:", "&#x1f4ab;"},
+ {":dizzy_face:", ":dizzy face:", "&#x1f635;"},
+ {":djibouti:", ":flag djibouti:", "&#x1f1e9;&#x1f1ef;"},
+ {":do_not_litter:", ":no littering:", "&#x1f6af;"},
+ {":dog:", ":dog face:", "&#x1f436;"},
+ {":dog2:", ":dog:", "&#x1f415;"},
+ {":dollar:", ":dollar banknote:", "&#x1f4b5;"},
+ {":dolls:", ":japanese dolls:", "&#x1f38e;"},
+ {":dolphin:", ":dolphin:", "&#x1f42c;"},
+ {":dominica:", ":flag dominica:", "&#x1f1e9;&#x1f1f2;"},
+ {":dominican_republic:", ":flag dominican republic:", "&#x1f1e9;&#x1f1f4;"},
+ {":door:", ":door:", "&#x1f6aa;"},
+ {":doughnut:", ":doughnut:", "&#x1f369;"},
+ {":dove:", ":dove:", "&#x1f54a;"},
+ {":dragon:", ":dragon:", "&#x1f409;"},
+ {":dragon_face:", ":dragon face:", "&#x1f432;"},
+ {":dress:", ":dress:", "&#x1f457;"},
+ {":dromedary_camel:", ":camel:", "&#x1f42a;"},
+ {":drooling_face:", ":drooling face:", "&#x1f924;"},
+ {":droplet:", ":droplet:", "&#x1f4a7;"},
+ {":drum:", ":drum:", "&#x1f941;"},
+ {":duck:", ":duck:", "&#x1f986;"},
+ {":dvd:", ":dvd:", "&#x1f4c0;"},
+ {":e-mail:", ":e-mail:", "&#x1f4e7;"},
+ {":eagle:", ":eagle:", "&#x1f985;"},
+ {":ear:", ":ear:", "&#x1f442;"},
+ {":ear_of_rice:", ":sheaf of rice:", "&#x1f33e;"},
+ {":earth_africa:", ":globe showing europe-africa:", "&#x1f30d;"},
+ {":earth_americas:", ":globe showing americas:", "&#x1f30e;"},
+ {":earth_asia:", ":globe showing asia-australia:", "&#x1f30f;"},
+ {":ecuador:", ":flag ecuador:", "&#x1f1ea;&#x1f1e8;"},
+ {":egg:", ":egg:", "&#x1f95a;"},
+ {":eggplant:", ":eggplant:", "&#x1f346;"},
+ {":egypt:", ":flag egypt:", "&#x1f1ea;&#x1f1ec;"},
+ {":eight:", ":keycap 8:", "&#x0038;&#xfe0f;&#x20e3;"},
+ {":eight_pointed_black_star:", ":eight-pointed star:", "&#x2734;"},
+ {":eight_spoked_asterisk:", ":eight-spoked asterisk:", "&#x2733;"},
+ {":el_salvador:", ":flag el salvador:", "&#x1f1f8;&#x1f1fb;"},
+ {":electric_plug:", ":electric plug:", "&#x1f50c;"},
+ {":elephant:", ":elephant:", "&#x1f418;"},
+ {":email:", ":envelope:", "&#x2709;"},
+ {":end:", ":end arrow:", "&#x1f51a;"},
+ {":envelope:", ":envelope:", "&#x2709;"},
+ {":envelope_with_arrow:", ":envelope with arrow:", "&#x1f4e9;"},
+ {":equatorial_guinea:", ":flag equatorial guinea:", "&#x1f1ec;&#x1f1f6;"},
+ {":eritrea:", ":flag eritrea:", "&#x1f1ea;&#x1f1f7;"},
+ {":es:", ":flag spain:", "&#x1f1ea;&#x1f1f8;"},
+ {":estonia:", ":flag estonia:", "&#x1f1ea;&#x1f1ea;"},
+ {":ethiopia:", ":flag ethiopia:", "&#x1f1ea;&#x1f1f9;"},
+ {":eu:", ":flag european union:", "&#x1f1ea;&#x1f1fa;"},
+ {":euro:", ":euro banknote:", "&#x1f4b6;"},
+ {":european_castle:", ":castle:", "&#x1f3f0;"},
+ {":european_post_office:", ":post office:", "&#x1f3e4;"},
+ {":european_union:", ":flag european union:", "&#x1f1ea;&#x1f1fa;"},
+ {":evergreen_tree:", ":evergreen tree:", "&#x1f332;"},
+ {":exclamation:", ":exclamation mark:", "&#x2757;"},
+ {":expressionless:", ":expressionless face:", "&#x1f611;"},
+ {":eye:", ":eye in speech bubble:", "&#x1f441;&#xfe0f;&#x200d;&#x1f5e8;&#xfe0f;"},
+ {":eye_speech_bubble:", ":eye in speech bubble:", "&#x1f441;&#xfe0f;&#x200d;&#x1f5e8;&#xfe0f;"},
+ {":eyeglasses:", ":glasses:", "&#x1f453;"},
+ {":eyes:", ":eyes:", "&#x1f440;"},
+ {":face_with_head_bandage:", ":face with head-bandage:", "&#x1f915;"},
+ {":face_with_thermometer:", ":face with thermometer:", "&#x1f912;"},
+ {":facepunch:", ":oncoming fist:", "&#x1f44a;"},
+ {":factory:", ":factory:", "&#x1f3ed;"},
+ {":falkland_islands:", ":flag falkland islands:", "&#x1f1eb;&#x1f1f0;"},
+ {":fallen_leaf:", ":fallen leaf:", "&#x1f342;"},
+ {":family:", ":family:", "&#x1f46a;"},
+ {":family_man_boy:", ":family man, woman, boy:", "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f466;"},
+ {":family_man_boy_boy:", ":family man, woman, boy, boy:", "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f466;&#x200d;&#x1f466;"},
+ {":family_man_girl:", ":family man, woman, girl:", "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;"},
+ {":family_man_girl_boy:", ":family man, woman, girl, boy:", "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f466;"},
+ {":family_man_girl_girl:", ":family man, woman, girl, girl:", "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f467;"},
+ {":family_man_man_boy:", ":family man, man, boy:", "&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f466;"},
+ {":family_man_man_boy_boy:", ":family man, man, boy, boy:", "&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f466;&#x200d;&#x1f466;"},
+ {":family_man_man_girl:", ":family man, man, girl:", "&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f467;"},
+ {":family_man_man_girl_boy:", ":family man, man, girl, boy:", "&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f467;&#x200d;&#x1f466;"},
+ {":family_man_man_girl_girl:", ":family man, man, girl, girl:", "&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f467;&#x200d;&#x1f467;"},
+ {":family_man_woman_boy:", ":family:", "&#x1f46a;"},
+ {":family_man_woman_boy_boy:", ":family man, woman, boy, boy:", "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f466;&#x200d;&#x1f466;"},
+ {":family_man_woman_girl:", ":family man, woman, girl:", "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;"},
+ {":family_man_woman_girl_boy:", ":family man, woman, girl, boy:", "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f466;"},
+ {":family_man_woman_girl_girl:", ":family man, woman, girl, girl:", "&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f467;"},
+ {":family_woman_boy:", ":family woman, woman, boy:", "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f466;"},
+ {":family_woman_boy_boy:", ":family woman, woman, boy, boy:", "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f466;&#x200d;&#x1f466;"},
+ {":family_woman_girl:", ":family woman, woman, girl:", "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;"},
+ {":family_woman_girl_boy:", ":family woman, woman, girl, boy:", "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f466;"},
+ {":family_woman_girl_girl:", ":family woman, woman, girl, girl:", "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f467;"},
+ {":family_woman_woman_boy:", ":family woman, woman, boy:", "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f466;"},
+ {":family_woman_woman_boy_boy:", ":family woman, woman, boy, boy:", "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f466;&#x200d;&#x1f466;"},
+ {":family_woman_woman_girl:", ":family woman, woman, girl:", "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;"},
+ {":family_woman_woman_girl_boy:", ":family woman, woman, girl, boy:", "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f466;"},
+ {":family_woman_woman_girl_girl:", ":family woman, woman, girl, girl:", "&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f467;"},
+ {":faroe_islands:", ":flag faroe islands:", "&#x1f1eb;&#x1f1f4;"},
+ {":fast_forward:", ":fast-forward button:", "&#x23e9;"},
+ {":fax:", ":fax machine:", "&#x1f4e0;"},
+ {":fearful:", ":fearful face:", "&#x1f628;"},
+ {":feet:", ":paw prints:", "&#x1f43e;"},
+ {":female_detective:", ":woman detective:", "&#x1f575;&#xfe0f;&#x200d;&#x2640;&#xfe0f;"},
+ {":ferris_wheel:", ":ferris wheel:", "&#x1f3a1;"},
+ {":ferry:", ":ferry:", "&#x26f4;"},
+ {":field_hockey:", ":field hockey:", "&#x1f3d1;"},
+ {":fiji:", ":flag fiji:", "&#x1f1eb;&#x1f1ef;"},
+ {":file_cabinet:", ":file cabinet:", "&#x1f5c4;"},
+ {":file_folder:", ":file folder:", "&#x1f4c1;"},
+ {":film_projector:", ":film projector:", "&#x1f4fd;"},
+ {":film_strip:", ":film frames:", "&#x1f39e;"},
+ {":finland:", ":flag finland:", "&#x1f1eb;&#x1f1ee;"},
+ {":fire:", ":fire:", "&#x1f525;"},
+ {":fire_engine:", ":fire engine:", "&#x1f692;"},
+ {":fireworks:", ":fireworks:", "&#x1f386;"},
+ {":first_quarter_moon:", ":first quarter moon:", "&#x1f313;"},
+ {":first_quarter_moon_with_face:", ":first quarter moon face:", "&#x1f31b;"},
+ {":fish:", ":fish:", "&#x1f41f;"},
+ {":fish_cake:", ":fish cake with swirl:", "&#x1f365;"},
+ {":fishing_pole_and_fish:", ":fishing pole:", "&#x1f3a3;"},
+ {":fist:", ":raised fist:", "&#x270a;"},
+ {":fist_left:", ":left-facing fist:", "&#x1f91b;"},
+ {":fist_oncoming:", ":oncoming fist:", "&#x1f44a;"},
+ {":fist_raised:", ":raised fist:", "&#x270a;"},
+ {":fist_right:", ":right-facing fist:", "&#x1f91c;"},
+ {":five:", ":keycap 5:", "&#x0035;&#xfe0f;&#x20e3;"},
+ {":flags:", ":carp streamer:", "&#x1f38f;"},
+ {":flashlight:", ":flashlight:", "&#x1f526;"},
+ {":fleur_de_lis:", ":fleur-de-lis:", "&#x269c;"},
+ {":flight_arrival:", ":airplane arrival:", "&#x1f6ec;"},
+ {":flight_departure:", ":airplane departure:", "&#x1f6eb;"},
+ {":flipper:", ":dolphin:", "&#x1f42c;"},
+ {":floppy_disk:", ":floppy disk:", "&#x1f4be;"},
+ {":flower_playing_cards:", ":flower playing cards:", "&#x1f3b4;"},
+ {":flushed:", ":flushed face:", "&#x1f633;"},
+ {":fog:", ":fog:", "&#x1f32b;"},
+ {":foggy:", ":foggy:", "&#x1f301;"},
+ {":football:", ":american football:", "&#x1f3c8;"},
+ {":footprints:", ":footprints:", "&#x1f463;"},
+ {":fork_and_knife:", ":fork and knife:", "&#x1f374;"},
+ {":fountain:", ":fountain:", "&#x26f2;"},
+ {":fountain_pen:", ":fountain pen:", "&#x1f58b;"},
+ {":four:", ":keycap 4:", "&#x0034;&#xfe0f;&#x20e3;"},
+ {":four_leaf_clover:", ":four leaf clover:", "&#x1f340;"},
+ {":fox_face:", ":fox face:", "&#x1f98a;"},
+ {":fr:", ":flag france:", "&#x1f1eb;&#x1f1f7;"},
+ {":framed_picture:", ":framed picture:", "&#x1f5bc;"},
+ {":free:", ":free button:", "&#x1f193;"},
+ {":french_guiana:", ":flag french guiana:", "&#x1f1ec;&#x1f1eb;"},
+ {":french_polynesia:", ":flag french polynesia:", "&#x1f1f5;&#x1f1eb;"},
+ {":french_southern_territories:", ":flag french southern territories:", "&#x1f1f9;&#x1f1eb;"},
+ {":fried_egg:", ":cooking:", "&#x1f373;"},
+ {":fried_shrimp:", ":fried shrimp:", "&#x1f364;"},
+ {":fries:", ":french fries:", "&#x1f35f;"},
+ {":frog:", ":frog face:", "&#x1f438;"},
+ {":frowning:", ":frowning face with open mouth:", "&#x1f626;"},
+ {":frowning_face:", ":frowning face:", "&#x2639;"},
+ {":frowning_man:", ":man frowning:", "&#x1f64d;&#x200d;&#x2642;&#xfe0f;"},
+ {":frowning_woman:", ":person frowning:", "&#x1f64d;"},
+ {":fu:", ":middle finger:", "&#x1f595;"},
+ {":fuelpump:", ":fuel pump:", "&#x26fd;"},
+ {":full_moon:", ":full moon:", "&#x1f315;"},
+ {":full_moon_with_face:", ":full moon face:", "&#x1f31d;"},
+ {":funeral_urn:", ":funeral urn:", "&#x26b1;"},
+ {":gabon:", ":flag gabon:", "&#x1f1ec;&#x1f1e6;"},
+ {":gambia:", ":flag gambia:", "&#x1f1ec;&#x1f1f2;"},
+ {":game_die:", ":game die:", "&#x1f3b2;"},
+ {":gb:", ":flag united kingdom:", "&#x1f1ec;&#x1f1e7;"},
+ {":gear:", ":gear:", "&#x2699;"},
+ {":gem:", ":gem stone:", "&#x1f48e;"},
+ {":gemini:", ":gemini:", "&#x264a;"},
+ {":georgia:", ":flag georgia:", "&#x1f1ec;&#x1f1ea;"},
+ {":ghana:", ":flag ghana:", "&#x1f1ec;&#x1f1ed;"},
+ {":ghost:", ":ghost:", "&#x1f47b;"},
+ {":gibraltar:", ":flag gibraltar:", "&#x1f1ec;&#x1f1ee;"},
+ {":gift:", ":wrapped gift:", "&#x1f381;"},
+ {":gift_heart:", ":heart with ribbon:", "&#x1f49d;"},
+ {":girl:", ":girl:", "&#x1f467;"},
+ {":globe_with_meridians:", ":globe with meridians:", "&#x1f310;"},
+ {":goal_net:", ":goal net:", "&#x1f945;"},
+ {":goat:", ":goat:", "&#x1f410;"},
+ {":golf:", ":flag in hole:", "&#x26f3;"},
+ {":golfing_man:", ":person golfing:", "&#x1f3cc;"},
+ {":golfing_woman:", ":woman golfing:", "&#x1f3cc;&#xfe0f;&#x200d;&#x2640;&#xfe0f;"},
+ {":gorilla:", ":gorilla:", "&#x1f98d;"},
+ {":grapes:", ":grapes:", "&#x1f347;"},
+ {":greece:", ":flag greece:", "&#x1f1ec;&#x1f1f7;"},
+ {":green_apple:", ":green apple:", "&#x1f34f;"},
+ {":green_book:", ":green book:", "&#x1f4d7;"},
+ {":green_heart:", ":green heart:", "&#x1f49a;"},
+ {":green_salad:", ":green salad:", "&#x1f957;"},
+ {":greenland:", ":flag greenland:", "&#x1f1ec;&#x1f1f1;"},
+ {":grenada:", ":flag grenada:", "&#x1f1ec;&#x1f1e9;"},
+ {":grey_exclamation:", ":white exclamation mark:", "&#x2755;"},
+ {":grey_question:", ":white question mark:", "&#x2754;"},
+ {":grimacing:", ":grimacing face:", "&#x1f62c;"},
+ {":grin:", ":beaming face with smiling eyes:", "&#x1f601;"},
+ {":grinning:", ":grinning face:", "&#x1f600;"},
+ {":guadeloupe:", ":flag guadeloupe:", "&#x1f1ec;&#x1f1f5;"},
+ {":guam:", ":flag guam:", "&#x1f1ec;&#x1f1fa;"},
+ {":guardsman:", ":guard:", "&#x1f482;"},
+ {":guardswoman:", ":woman guard:", "&#x1f482;&#x200d;&#x2640;&#xfe0f;"},
+ {":guatemala:", ":flag guatemala:", "&#x1f1ec;&#x1f1f9;"},
+ {":guernsey:", ":flag guernsey:", "&#x1f1ec;&#x1f1ec;"},
+ {":guinea:", ":flag guinea:", "&#x1f1ec;&#x1f1f3;"},
+ {":guinea_bissau:", ":flag guinea-bissau:", "&#x1f1ec;&#x1f1fc;"},
+ {":guitar:", ":guitar:", "&#x1f3b8;"},
+ {":gun:", ":pistol:", "&#x1f52b;"},
+ {":guyana:", ":flag guyana:", "&#x1f1ec;&#x1f1fe;"},
+ {":haircut:", ":person getting haircut:", "&#x1f487;"},
+ {":haircut_man:", ":man getting haircut:", "&#x1f487;&#x200d;&#x2642;&#xfe0f;"},
+ {":haircut_woman:", ":person getting haircut:", "&#x1f487;"},
+ {":haiti:", ":flag haiti:", "&#x1f1ed;&#x1f1f9;"},
+ {":hamburger:", ":hamburger:", "&#x1f354;"},
+ {":hammer:", ":hammer:", "&#x1f528;"},
+ {":hammer_and_pick:", ":hammer and pick:", "&#x2692;"},
+ {":hammer_and_wrench:", ":hammer and wrench:", "&#x1f6e0;"},
+ {":hamster:", ":hamster face:", "&#x1f439;"},
+ {":hand:", ":raised hand:", "&#x270b;"},
+ {":handbag:", ":handbag:", "&#x1f45c;"},
+ {":handshake:", ":handshake:", "&#x1f91d;"},
+ {":hankey:", ":pile of poo:", "&#x1f4a9;"},
+ {":hash:", ":keycap #:", "&#x0023;&#xfe0f;&#x20e3;"},
+ {":hatched_chick:", ":front-facing baby chick:", "&#x1f425;"},
+ {":hatching_chick:", ":hatching chick:", "&#x1f423;"},
+ {":headphones:", ":headphone:", "&#x1f3a7;"},
+ {":hear_no_evil:", ":hear-no-evil monkey:", "&#x1f649;"},
+ {":heart:", ":red heart:", "&#x2764;"},
+ {":heart_decoration:", ":heart decoration:", "&#x1f49f;"},
+ {":heart_eyes:", ":smiling face with heart-eyes:", "&#x1f60d;"},
+ {":heart_eyes_cat:", ":smiling cat face with heart-eyes:", "&#x1f63b;"},
+ {":heartbeat:", ":beating heart:", "&#x1f493;"},
+ {":heartpulse:", ":growing heart:", "&#x1f497;"},
+ {":hearts:", ":heart suit:", "&#x2665;"},
+ {":heavy_check_mark:", ":heavy check mark:", "&#x2714;"},
+ {":heavy_division_sign:", ":heavy division sign:", "&#x2797;"},
+ {":heavy_dollar_sign:", ":heavy dollar sign:", "&#x1f4b2;"},
+ {":heavy_exclamation_mark:", ":exclamation mark:", "&#x2757;"},
+ {":heavy_heart_exclamation:", ":heavy heart exclamation:", "&#x2763;"},
+ {":heavy_minus_sign:", ":heavy minus sign:", "&#x2796;"},
+ {":heavy_multiplication_x:", ":heavy multiplication x:", "&#x2716;"},
+ {":heavy_plus_sign:", ":heavy plus sign:", "&#x2795;"},
+ {":helicopter:", ":helicopter:", "&#x1f681;"},
+ {":herb:", ":herb:", "&#x1f33f;"},
+ {":hibiscus:", ":hibiscus:", "&#x1f33a;"},
+ {":high_brightness:", ":bright button:", "&#x1f506;"},
+ {":high_heel:", ":high-heeled shoe:", "&#x1f460;"},
+ {":hocho:", ":kitchen knife:", "&#x1f52a;"},
+ {":hole:", ":hole:", "&#x1f573;"},
+ {":honduras:", ":flag honduras:", "&#x1f1ed;&#x1f1f3;"},
+ {":honey_pot:", ":honey pot:", "&#x1f36f;"},
+ {":honeybee:", ":honeybee:", "&#x1f41d;"},
+ {":hong_kong:", ":flag hong kong sar china:", "&#x1f1ed;&#x1f1f0;"},
+ {":horse:", ":horse face:", "&#x1f434;"},
+ {":horse_racing:", ":horse racing:", "&#x1f3c7;"},
+ {":hospital:", ":hospital:", "&#x1f3e5;"},
+ {":hot_pepper:", ":hot pepper:", "&#x1f336;"},
+ {":hotdog:", ":hot dog:", "&#x1f32d;"},
+ {":hotel:", ":hotel:", "&#x1f3e8;"},
+ {":hotsprings:", ":hot springs:", "&#x2668;"},
+ {":hourglass:", ":hourglass done:", "&#x231b;"},
+ {":hourglass_flowing_sand:", ":hourglass not done:", "&#x23f3;"},
+ {":house:", ":house:", "&#x1f3e0;"},
+ {":house_with_garden:", ":house with garden:", "&#x1f3e1;"},
+ {":houses:", ":houses:", "&#x1f3d8;"},
+ {":hugs:", ":hugging face:", "&#x1f917;"},
+ {":hungary:", ":flag hungary:", "&#x1f1ed;&#x1f1fa;"},
+ {":hushed:", ":hushed face:", "&#x1f62f;"},
+ {":ice_cream:", ":ice cream:", "&#x1f368;"},
+ {":ice_hockey:", ":ice hockey:", "&#x1f3d2;"},
+ {":ice_skate:", ":ice skate:", "&#x26f8;"},
+ {":icecream:", ":soft ice cream:", "&#x1f366;"},
+ {":iceland:", ":flag iceland:", "&#x1f1ee;&#x1f1f8;"},
+ {":id:", ":id button:", "&#x1f194;"},
+ {":ideograph_advantage:", ":japanese \"bargain\" button:", "&#x1f250;"},
+ {":imp:", ":angry face with horns:", "&#x1f47f;"},
+ {":inbox_tray:", ":inbox tray:", "&#x1f4e5;"},
+ {":incoming_envelope:", ":incoming envelope:", "&#x1f4e8;"},
+ {":india:", ":flag india:", "&#x1f1ee;&#x1f1f3;"},
+ {":indonesia:", ":flag indonesia:", "&#x1f1ee;&#x1f1e9;"},
+ {":information_desk_person:", ":person tipping hand:", "&#x1f481;"},
+ {":information_source:", ":information:", "&#x2139;"},
+ {":innocent:", ":smiling face with halo:", "&#x1f607;"},
+ {":interrobang:", ":exclamation question mark:", "&#x2049;"},
+ {":iphone:", ":mobile phone:", "&#x1f4f1;"},
+ {":iran:", ":flag iran:", "&#x1f1ee;&#x1f1f7;"},
+ {":iraq:", ":flag iraq:", "&#x1f1ee;&#x1f1f6;"},
+ {":ireland:", ":flag ireland:", "&#x1f1ee;&#x1f1ea;"},
+ {":isle_of_man:", ":flag isle of man:", "&#x1f1ee;&#x1f1f2;"},
+ {":israel:", ":flag israel:", "&#x1f1ee;&#x1f1f1;"},
+ {":it:", ":flag italy:", "&#x1f1ee;&#x1f1f9;"},
+ {":izakaya_lantern:", ":red paper lantern:", "&#x1f3ee;"},
+ {":jack_o_lantern:", ":jack-o-lantern:", "&#x1f383;"},
+ {":jamaica:", ":flag jamaica:", "&#x1f1ef;&#x1f1f2;"},
+ {":japan:", ":map of japan:", "&#x1f5fe;"},
+ {":japanese_castle:", ":japanese castle:", "&#x1f3ef;"},
+ {":japanese_goblin:", ":goblin:", "&#x1f47a;"},
+ {":japanese_ogre:", ":ogre:", "&#x1f479;"},
+ {":jeans:", ":jeans:", "&#x1f456;"},
+ {":jersey:", ":flag jersey:", "&#x1f1ef;&#x1f1ea;"},
+ {":jordan:", ":flag jordan:", "&#x1f1ef;&#x1f1f4;"},
+ {":joy:", ":face with tears of joy:", "&#x1f602;"},
+ {":joy_cat:", ":cat face with tears of joy:", "&#x1f639;"},
+ {":joystick:", ":joystick:", "&#x1f579;"},
+ {":jp:", ":flag japan:", "&#x1f1ef;&#x1f1f5;"},
+ {":kaaba:", ":kaaba:", "&#x1f54b;"},
+ {":kazakhstan:", ":flag kazakhstan:", "&#x1f1f0;&#x1f1ff;"},
+ {":kenya:", ":flag kenya:", "&#x1f1f0;&#x1f1ea;"},
+ {":key:", ":key:", "&#x1f511;"},
+ {":keyboard:", ":keyboard:", "&#x2328;"},
+ {":keycap_ten:", ":keycap 10:", "&#x1f51f;"},
+ {":kick_scooter:", ":kick scooter:", "&#x1f6f4;"},
+ {":kimono:", ":kimono:", "&#x1f458;"},
+ {":kiribati:", ":flag kiribati:", "&#x1f1f0;&#x1f1ee;"},
+ {":kiss:", ":kiss mark:", "&#x1f48b;"},
+ {":kissing:", ":kissing face:", "&#x1f617;"},
+ {":kissing_cat:", ":kissing cat face:", "&#x1f63d;"},
+ {":kissing_closed_eyes:", ":kissing face with closed eyes:", "&#x1f61a;"},
+ {":kissing_heart:", ":face blowing a kiss:", "&#x1f618;"},
+ {":kissing_smiling_eyes:", ":kissing face with smiling eyes:", "&#x1f619;"},
+ {":kiwi_fruit:", ":kiwi fruit:", "&#x1f95d;"},
+ {":knife:", ":kitchen knife:", "&#x1f52a;"},
+ {":koala:", ":koala:", "&#x1f428;"},
+ {":koko:", ":japanese \"here\" button:", "&#x1f201;"},
+ {":kosovo:", ":flag kosovo:", "&#x1f1fd;&#x1f1f0;"},
+ {":kr:", ":flag south korea:", "&#x1f1f0;&#x1f1f7;"},
+ {":kuwait:", ":flag kuwait:", "&#x1f1f0;&#x1f1fc;"},
+ {":kyrgyzstan:", ":flag kyrgyzstan:", "&#x1f1f0;&#x1f1ec;"},
+ {":label:", ":label:", "&#x1f3f7;"},
+ {":lantern:", ":red paper lantern:", "&#x1f3ee;"},
+ {":laos:", ":flag laos:", "&#x1f1f1;&#x1f1e6;"},
+ {":large_blue_circle:", ":blue circle:", "&#x1f535;"},
+ {":large_blue_diamond:", ":large blue diamond:", "&#x1f537;"},
+ {":large_orange_diamond:", ":large orange diamond:", "&#x1f536;"},
+ {":last_quarter_moon:", ":last quarter moon:", "&#x1f317;"},
+ {":last_quarter_moon_with_face:", ":last quarter moon face:", "&#x1f31c;"},
+ {":latin_cross:", ":latin cross:", "&#x271d;"},
+ {":latvia:", ":flag latvia:", "&#x1f1f1;&#x1f1fb;"},
+ {":laughing:", ":grinning squinting face:", "&#x1f606;"},
+ {":leaves:", ":leaf fluttering in wind:", "&#x1f343;"},
+ {":lebanon:", ":flag lebanon:", "&#x1f1f1;&#x1f1e7;"},
+ {":ledger:", ":ledger:", "&#x1f4d2;"},
+ {":left_luggage:", ":left luggage:", "&#x1f6c5;"},
+ {":left_right_arrow:", ":left-right arrow:", "&#x2194;"},
+ {":leftwards_arrow_with_hook:", ":right arrow curving left:", "&#x21a9;"},
+ {":lemon:", ":lemon:", "&#x1f34b;"},
+ {":leo:", ":leo:", "&#x264c;"},
+ {":leopard:", ":leopard:", "&#x1f406;"},
+ {":lesotho:", ":flag lesotho:", "&#x1f1f1;&#x1f1f8;"},
+ {":level_slider:", ":level slider:", "&#x1f39a;"},
+ {":liberia:", ":flag liberia:", "&#x1f1f1;&#x1f1f7;"},
+ {":libra:", ":libra:", "&#x264e;"},
+ {":libya:", ":flag libya:", "&#x1f1f1;&#x1f1fe;"},
+ {":liechtenstein:", ":flag liechtenstein:", "&#x1f1f1;&#x1f1ee;"},
+ {":light_rail:", ":light rail:", "&#x1f688;"},
+ {":link:", ":link:", "&#x1f517;"},
+ {":lion:", ":lion face:", "&#x1f981;"},
+ {":lips:", ":mouth:", "&#x1f444;"},
+ {":lipstick:", ":lipstick:", "&#x1f484;"},
+ {":lithuania:", ":flag lithuania:", "&#x1f1f1;&#x1f1f9;"},
+ {":lizard:", ":lizard:", "&#x1f98e;"},
+ {":lock:", ":locked:", "&#x1f512;"},
+ {":lock_with_ink_pen:", ":locked with pen:", "&#x1f50f;"},
+ {":lollipop:", ":lollipop:", "&#x1f36d;"},
+ {":loop:", ":double curly loop:", "&#x27bf;"},
+ {":loud_sound:", ":speaker high volume:", "&#x1f50a;"},
+ {":loudspeaker:", ":loudspeaker:", "&#x1f4e2;"},
+ {":love_hotel:", ":love hotel:", "&#x1f3e9;"},
+ {":love_letter:", ":love letter:", "&#x1f48c;"},
+ {":low_brightness:", ":dim button:", "&#x1f505;"},
+ {":luxembourg:", ":flag luxembourg:", "&#x1f1f1;&#x1f1fa;"},
+ {":lying_face:", ":lying face:", "&#x1f925;"},
+ {":m:", ":circled m:", "&#x24c2;"},
+ {":macau:", ":flag macau sar china:", "&#x1f1f2;&#x1f1f4;"},
+ {":macedonia:", ":flag macedonia:", "&#x1f1f2;&#x1f1f0;"},
+ {":madagascar:", ":flag madagascar:", "&#x1f1f2;&#x1f1ec;"},
+ {":mag:", ":magnifying glass tilted left:", "&#x1f50d;"},
+ {":mag_right:", ":magnifying glass tilted right:", "&#x1f50e;"},
+ {":mahjong:", ":mahjong red dragon:", "&#x1f004;"},
+ {":mailbox:", ":closed mailbox with raised flag:", "&#x1f4eb;"},
+ {":mailbox_closed:", ":closed mailbox with lowered flag:", "&#x1f4ea;"},
+ {":mailbox_with_mail:", ":open mailbox with raised flag:", "&#x1f4ec;"},
+ {":mailbox_with_no_mail:", ":open mailbox with lowered flag:", "&#x1f4ed;"},
+ {":malawi:", ":flag malawi:", "&#x1f1f2;&#x1f1fc;"},
+ {":malaysia:", ":flag malaysia:", "&#x1f1f2;&#x1f1fe;"},
+ {":maldives:", ":flag maldives:", "&#x1f1f2;&#x1f1fb;"},
+ {":male_detective:", ":detective:", "&#x1f575;"},
+ {":mali:", ":flag mali:", "&#x1f1f2;&#x1f1f1;"},
+ {":malta:", ":flag malta:", "&#x1f1f2;&#x1f1f9;"},
+ {":man:", ":man:", "&#x1f468;"},
+ {":man_artist:", ":man artist:", "&#x1f468;&#x200d;&#x1f3a8;"},
+ {":man_astronaut:", ":man astronaut:", "&#x1f468;&#x200d;&#x1f680;"},
+ {":man_cartwheeling:", ":man cartwheeling:", "&#x1f938;&#x200d;&#x2642;&#xfe0f;"},
+ {":man_cook:", ":man cook:", "&#x1f468;&#x200d;&#x1f373;"},
+ {":man_dancing:", ":man dancing:", "&#x1f57a;"},
+ {":man_facepalming:", ":man facepalming:", "&#x1f926;&#x200d;&#x2642;&#xfe0f;"},
+ {":man_factory_worker:", ":man factory worker:", "&#x1f468;&#x200d;&#x1f3ed;"},
+ {":man_farmer:", ":man farmer:", "&#x1f468;&#x200d;&#x1f33e;"},
+ {":man_firefighter:", ":man firefighter:", "&#x1f468;&#x200d;&#x1f692;"},
+ {":man_health_worker:", ":man health worker:", "&#x1f468;&#x200d;&#x2695;&#xfe0f;"},
+ {":man_in_tuxedo:", ":man in tuxedo:", "&#x1f935;"},
+ {":man_judge:", ":man judge:", "&#x1f468;&#x200d;&#x2696;&#xfe0f;"},
+ {":man_juggling:", ":man juggling:", "&#x1f939;&#x200d;&#x2642;&#xfe0f;"},
+ {":man_mechanic:", ":man mechanic:", "&#x1f468;&#x200d;&#x1f527;"},
+ {":man_office_worker:", ":man office worker:", "&#x1f468;&#x200d;&#x1f4bc;"},
+ {":man_pilot:", ":man pilot:", "&#x1f468;&#x200d;&#x2708;&#xfe0f;"},
+ {":man_playing_handball:", ":man playing handball:", "&#x1f93e;&#x200d;&#x2642;&#xfe0f;"},
+ {":man_playing_water_polo:", ":man playing water polo:", "&#x1f93d;&#x200d;&#x2642;&#xfe0f;"},
+ {":man_scientist:", ":man scientist:", "&#x1f468;&#x200d;&#x1f52c;"},
+ {":man_shrugging:", ":man shrugging:", "&#x1f937;&#x200d;&#x2642;&#xfe0f;"},
+ {":man_singer:", ":man singer:", "&#x1f468;&#x200d;&#x1f3a4;"},
+ {":man_student:", ":man student:", "&#x1f468;&#x200d;&#x1f393;"},
+ {":man_teacher:", ":man teacher:", "&#x1f468;&#x200d;&#x1f3eb;"},
+ {":man_technologist:", ":man technologist:", "&#x1f468;&#x200d;&#x1f4bb;"},
+ {":man_with_gua_pi_mao:", ":man with chinese cap:", "&#x1f472;"},
+ {":man_with_turban:", ":person wearing turban:", "&#x1f473;"},
+ {":mandarin:", ":tangerine:", "&#x1f34a;"},
+ {":mans_shoe:", ":man's shoe:", "&#x1f45e;"},
+ {":mantelpiece_clock:", ":mantelpiece clock:", "&#x1f570;"},
+ {":maple_leaf:", ":maple leaf:", "&#x1f341;"},
+ {":marshall_islands:", ":flag marshall islands:", "&#x1f1f2;&#x1f1ed;"},
+ {":martial_arts_uniform:", ":martial arts uniform:", "&#x1f94b;"},
+ {":martinique:", ":flag martinique:", "&#x1f1f2;&#x1f1f6;"},
+ {":mask:", ":face with medical mask:", "&#x1f637;"},
+ {":massage:", ":person getting massage:", "&#x1f486;"},
+ {":massage_man:", ":man getting massage:", "&#x1f486;&#x200d;&#x2642;&#xfe0f;"},
+ {":massage_woman:", ":person getting massage:", "&#x1f486;"},
+ {":mauritania:", ":flag mauritania:", "&#x1f1f2;&#x1f1f7;"},
+ {":mauritius:", ":flag mauritius:", "&#x1f1f2;&#x1f1fa;"},
+ {":mayotte:", ":flag mayotte:", "&#x1f1fe;&#x1f1f9;"},
+ {":meat_on_bone:", ":meat on bone:", "&#x1f356;"},
+ {":medal_military:", ":military medal:", "&#x1f396;"},
+ {":medal_sports:", ":sports medal:", "&#x1f3c5;"},
+ {":mega:", ":megaphone:", "&#x1f4e3;"},
+ {":melon:", ":melon:", "&#x1f348;"},
+ {":memo:", ":memo:", "&#x1f4dd;"},
+ {":men_wrestling:", ":men wrestling:", "&#x1f93c;&#x200d;&#x2642;&#xfe0f;"},
+ {":menorah:", ":menorah:", "&#x1f54e;"},
+ {":mens:", ":men's room:", "&#x1f6b9;"},
+ {":metal:", ":sign of the horns:", "&#x1f918;"},
+ {":metro:", ":metro:", "&#x1f687;"},
+ {":mexico:", ":flag mexico:", "&#x1f1f2;&#x1f1fd;"},
+ {":micronesia:", ":flag micronesia:", "&#x1f1eb;&#x1f1f2;"},
+ {":microphone:", ":microphone:", "&#x1f3a4;"},
+ {":microscope:", ":microscope:", "&#x1f52c;"},
+ {":middle_finger:", ":middle finger:", "&#x1f595;"},
+ {":milk_glass:", ":glass of milk:", "&#x1f95b;"},
+ {":milky_way:", ":milky way:", "&#x1f30c;"},
+ {":minibus:", ":minibus:", "&#x1f690;"},
+ {":minidisc:", ":computer disk:", "&#x1f4bd;"},
+ {":mobile_phone_off:", ":mobile phone off:", "&#x1f4f4;"},
+ {":moldova:", ":flag moldova:", "&#x1f1f2;&#x1f1e9;"},
+ {":monaco:", ":flag monaco:", "&#x1f1f2;&#x1f1e8;"},
+ {":money_mouth_face:", ":money-mouth face:", "&#x1f911;"},
+ {":money_with_wings:", ":money with wings:", "&#x1f4b8;"},
+ {":moneybag:", ":money bag:", "&#x1f4b0;"},
+ {":mongolia:", ":flag mongolia:", "&#x1f1f2;&#x1f1f3;"},
+ {":monkey:", ":monkey:", "&#x1f412;"},
+ {":monkey_face:", ":monkey face:", "&#x1f435;"},
+ {":monorail:", ":monorail:", "&#x1f69d;"},
+ {":montenegro:", ":flag montenegro:", "&#x1f1f2;&#x1f1ea;"},
+ {":montserrat:", ":flag montserrat:", "&#x1f1f2;&#x1f1f8;"},
+ {":moon:", ":waxing gibbous moon:", "&#x1f314;"},
+ {":morocco:", ":flag morocco:", "&#x1f1f2;&#x1f1e6;"},
+ {":mortar_board:", ":graduation cap:", "&#x1f393;"},
+ {":mosque:", ":mosque:", "&#x1f54c;"},
+ {":motor_boat:", ":motor boat:", "&#x1f6e5;"},
+ {":motor_scooter:", ":motor scooter:", "&#x1f6f5;"},
+ {":motorcycle:", ":motorcycle:", "&#x1f3cd;"},
+ {":motorway:", ":motorway:", "&#x1f6e3;"},
+ {":mount_fuji:", ":mount fuji:", "&#x1f5fb;"},
+ {":mountain:", ":mountain:", "&#x26f0;"},
+ {":mountain_bicyclist:", ":person mountain biking:", "&#x1f6b5;"},
+ {":mountain_biking_man:", ":person mountain biking:", "&#x1f6b5;"},
+ {":mountain_biking_woman:", ":woman mountain biking:", "&#x1f6b5;&#x200d;&#x2640;&#xfe0f;"},
+ {":mountain_cableway:", ":mountain cableway:", "&#x1f6a0;"},
+ {":mountain_railway:", ":mountain railway:", "&#x1f69e;"},
+ {":mountain_snow:", ":snow-capped mountain:", "&#x1f3d4;"},
+ {":mouse:", ":mouse face:", "&#x1f42d;"},
+ {":mouse2:", ":mouse:", "&#x1f401;"},
+ {":movie_camera:", ":movie camera:", "&#x1f3a5;"},
+ {":moyai:", ":moai:", "&#x1f5ff;"},
+ {":mozambique:", ":flag mozambique:", "&#x1f1f2;&#x1f1ff;"},
+ {":mrs_claus:", ":mrs. claus:", "&#x1f936;"},
+ {":muscle:", ":flexed biceps:", "&#x1f4aa;"},
+ {":mushroom:", ":mushroom:", "&#x1f344;"},
+ {":musical_keyboard:", ":musical keyboard:", "&#x1f3b9;"},
+ {":musical_note:", ":musical note:", "&#x1f3b5;"},
+ {":musical_score:", ":musical score:", "&#x1f3bc;"},
+ {":mute:", ":muted speaker:", "&#x1f507;"},
+ {":myanmar:", ":flag myanmar (burma):", "&#x1f1f2;&#x1f1f2;"},
+ {":nail_care:", ":nail polish:", "&#x1f485;"},
+ {":name_badge:", ":name badge:", "&#x1f4db;"},
+ {":namibia:", ":flag namibia:", "&#x1f1f3;&#x1f1e6;"},
+ {":national_park:", ":national park:", "&#x1f3de;"},
+ {":nauru:", ":flag nauru:", "&#x1f1f3;&#x1f1f7;"},
+ {":nauseated_face:", ":nauseated face:", "&#x1f922;"},
+ {":necktie:", ":necktie:", "&#x1f454;"},
+ {":negative_squared_cross_mark:", ":cross mark button:", "&#x274e;"},
+ {":nepal:", ":flag nepal:", "&#x1f1f3;&#x1f1f5;"},
+ {":nerd_face:", ":nerd face:", "&#x1f913;"},
+ {":netherlands:", ":flag netherlands:", "&#x1f1f3;&#x1f1f1;"},
+ {":neutral_face:", ":neutral face:", "&#x1f610;"},
+ {":new:", ":new button:", "&#x1f195;"},
+ {":new_caledonia:", ":flag new caledonia:", "&#x1f1f3;&#x1f1e8;"},
+ {":new_moon:", ":new moon:", "&#x1f311;"},
+ {":new_moon_with_face:", ":new moon face:", "&#x1f31a;"},
+ {":new_zealand:", ":flag new zealand:", "&#x1f1f3;&#x1f1ff;"},
+ {":newspaper:", ":newspaper:", "&#x1f4f0;"},
+ {":newspaper_roll:", ":rolled-up newspaper:", "&#x1f5de;"},
+ {":next_track_button:", ":next track button:", "&#x23ed;"},
+ {":ng:", ":ng button:", "&#x1f196;"},
+ {":ng_man:", ":man gesturing no:", "&#x1f645;&#x200d;&#x2642;&#xfe0f;"},
+ {":ng_woman:", ":person gesturing no:", "&#x1f645;"},
+ {":nicaragua:", ":flag nicaragua:", "&#x1f1f3;&#x1f1ee;"},
+ {":niger:", ":flag niger:", "&#x1f1f3;&#x1f1ea;"},
+ {":nigeria:", ":flag nigeria:", "&#x1f1f3;&#x1f1ec;"},
+ {":night_with_stars:", ":night with stars:", "&#x1f303;"},
+ {":nine:", ":keycap 9:", "&#x0039;&#xfe0f;&#x20e3;"},
+ {":niue:", ":flag niue:", "&#x1f1f3;&#x1f1fa;"},
+ {":no_bell:", ":bell with slash:", "&#x1f515;"},
+ {":no_bicycles:", ":no bicycles:", "&#x1f6b3;"},
+ {":no_entry:", ":no entry:", "&#x26d4;"},
+ {":no_entry_sign:", ":prohibited:", "&#x1f6ab;"},
+ {":no_good:", ":person gesturing no:", "&#x1f645;"},
+ {":no_good_man:", ":man gesturing no:", "&#x1f645;&#x200d;&#x2642;&#xfe0f;"},
+ {":no_good_woman:", ":person gesturing no:", "&#x1f645;"},
+ {":no_mobile_phones:", ":no mobile phones:", "&#x1f4f5;"},
+ {":no_mouth:", ":face without mouth:", "&#x1f636;"},
+ {":no_pedestrians:", ":no pedestrians:", "&#x1f6b7;"},
+ {":no_smoking:", ":no smoking:", "&#x1f6ad;"},
+ {":non-potable_water:", ":non-potable water:", "&#x1f6b1;"},
+ {":norfolk_island:", ":flag norfolk island:", "&#x1f1f3;&#x1f1eb;"},
+ {":north_korea:", ":flag north korea:", "&#x1f1f0;&#x1f1f5;"},
+ {":northern_mariana_islands:", ":flag northern mariana islands:", "&#x1f1f2;&#x1f1f5;"},
+ {":norway:", ":flag norway:", "&#x1f1f3;&#x1f1f4;"},
+ {":nose:", ":nose:", "&#x1f443;"},
+ {":notebook:", ":notebook:", "&#x1f4d3;"},
+ {":notebook_with_decorative_cover:", ":notebook with decorative cover:", "&#x1f4d4;"},
+ {":notes:", ":musical notes:", "&#x1f3b6;"},
+ {":nut_and_bolt:", ":nut and bolt:", "&#x1f529;"},
+ {":o:", ":heavy large circle:", "&#x2b55;"},
+ {":o2:", ":o button (blood type):", "&#x1f17e;"},
+ {":ocean:", ":water wave:", "&#x1f30a;"},
+ {":octopus:", ":octopus:", "&#x1f419;"},
+ {":oden:", ":oden:", "&#x1f362;"},
+ {":office:", ":office building:", "&#x1f3e2;"},
+ {":oil_drum:", ":oil drum:", "&#x1f6e2;"},
+ {":ok:", ":ok button:", "&#x1f197;"},
+ {":ok_hand:", ":ok hand:", "&#x1f44c;"},
+ {":ok_man:", ":man gesturing ok:", "&#x1f646;&#x200d;&#x2642;&#xfe0f;"},
+ {":ok_woman:", ":person gesturing ok:", "&#x1f646;"},
+ {":old_key:", ":old key:", "&#x1f5dd;"},
+ {":older_man:", ":old man:", "&#x1f474;"},
+ {":older_woman:", ":old woman:", "&#x1f475;"},
+ {":om:", ":om:", "&#x1f549;"},
+ {":oman:", ":flag oman:", "&#x1f1f4;&#x1f1f2;"},
+ {":on:", ":on! arrow:", "&#x1f51b;"},
+ {":oncoming_automobile:", ":oncoming automobile:", "&#x1f698;"},
+ {":oncoming_bus:", ":oncoming bus:", "&#x1f68d;"},
+ {":oncoming_police_car:", ":oncoming police car:", "&#x1f694;"},
+ {":oncoming_taxi:", ":oncoming taxi:", "&#x1f696;"},
+ {":one:", ":keycap 1:", "&#x0031;&#xfe0f;&#x20e3;"},
+ {":open_book:", ":open book:", "&#x1f4d6;"},
+ {":open_file_folder:", ":open file folder:", "&#x1f4c2;"},
+ {":open_hands:", ":open hands:", "&#x1f450;"},
+ {":open_mouth:", ":face with open mouth:", "&#x1f62e;"},
+ {":open_umbrella:", ":umbrella:", "&#x2602;"},
+ {":ophiuchus:", ":ophiuchus:", "&#x26ce;"},
+ {":orange:", ":tangerine:", "&#x1f34a;"},
+ {":orange_book:", ":orange book:", "&#x1f4d9;"},
+ {":orthodox_cross:", ":orthodox cross:", "&#x2626;"},
+ {":outbox_tray:", ":outbox tray:", "&#x1f4e4;"},
+ {":owl:", ":owl:", "&#x1f989;"},
+ {":ox:", ":ox:", "&#x1f402;"},
+ {":package:", ":package:", "&#x1f4e6;"},
+ {":page_facing_up:", ":page facing up:", "&#x1f4c4;"},
+ {":page_with_curl:", ":page with curl:", "&#x1f4c3;"},
+ {":pager:", ":pager:", "&#x1f4df;"},
+ {":paintbrush:", ":paintbrush:", "&#x1f58c;"},
+ {":pakistan:", ":flag pakistan:", "&#x1f1f5;&#x1f1f0;"},
+ {":palau:", ":flag palau:", "&#x1f1f5;&#x1f1fc;"},
+ {":palestinian_territories:", ":flag palestinian territories:", "&#x1f1f5;&#x1f1f8;"},
+ {":palm_tree:", ":palm tree:", "&#x1f334;"},
+ {":panama:", ":flag panama:", "&#x1f1f5;&#x1f1e6;"},
+ {":pancakes:", ":pancakes:", "&#x1f95e;"},
+ {":panda_face:", ":panda face:", "&#x1f43c;"},
+ {":paperclip:", ":paperclip:", "&#x1f4ce;"},
+ {":paperclips:", ":linked paperclips:", "&#x1f587;"},
+ {":papua_new_guinea:", ":flag papua new guinea:", "&#x1f1f5;&#x1f1ec;"},
+ {":paraguay:", ":flag paraguay:", "&#x1f1f5;&#x1f1fe;"},
+ {":parasol_on_ground:", ":umbrella on ground:", "&#x26f1;"},
+ {":parking:", ":p button:", "&#x1f17f;"},
+ {":part_alternation_mark:", ":part alternation mark:", "&#x303d;"},
+ {":partly_sunny:", ":sun behind cloud:", "&#x26c5;"},
+ {":passenger_ship:", ":passenger ship:", "&#x1f6f3;"},
+ {":passport_control:", ":passport control:", "&#x1f6c2;"},
+ {":pause_button:", ":pause button:", "&#x23f8;"},
+ {":paw_prints:", ":paw prints:", "&#x1f43e;"},
+ {":peace_symbol:", ":peace symbol:", "&#x262e;"},
+ {":peach:", ":peach:", "&#x1f351;"},
+ {":peanuts:", ":peanuts:", "&#x1f95c;"},
+ {":pear:", ":pear:", "&#x1f350;"},
+ {":pen:", ":pen:", "&#x1f58a;"},
+ {":pencil:", ":memo:", "&#x1f4dd;"},
+ {":pencil2:", ":pencil:", "&#x270f;"},
+ {":penguin:", ":penguin:", "&#x1f427;"},
+ {":pensive:", ":pensive face:", "&#x1f614;"},
+ {":performing_arts:", ":performing arts:", "&#x1f3ad;"},
+ {":persevere:", ":persevering face:", "&#x1f623;"},
+ {":person_fencing:", ":person fencing:", "&#x1f93a;"},
+ {":person_frowning:", ":person frowning:", "&#x1f64d;"},
+ {":person_with_blond_hair:", ":person blond hair:", "&#x1f471;"},
+ {":person_with_pouting_face:", ":person pouting:", "&#x1f64e;"},
+ {":peru:", ":flag peru:", "&#x1f1f5;&#x1f1ea;"},
+ {":philippines:", ":flag philippines:", "&#x1f1f5;&#x1f1ed;"},
+ {":phone:", ":telephone:", "&#x260e;"},
+ {":pick:", ":pick:", "&#x26cf;"},
+ {":pig:", ":pig face:", "&#x1f437;"},
+ {":pig2:", ":pig:", "&#x1f416;"},
+ {":pig_nose:", ":pig nose:", "&#x1f43d;"},
+ {":pill:", ":pill:", "&#x1f48a;"},
+ {":pineapple:", ":pineapple:", "&#x1f34d;"},
+ {":ping_pong:", ":ping pong:", "&#x1f3d3;"},
+ {":pisces:", ":pisces:", "&#x2653;"},
+ {":pitcairn_islands:", ":flag pitcairn islands:", "&#x1f1f5;&#x1f1f3;"},
+ {":pizza:", ":pizza:", "&#x1f355;"},
+ {":place_of_worship:", ":place of worship:", "&#x1f6d0;"},
+ {":plate_with_cutlery:", ":fork and knife with plate:", "&#x1f37d;"},
+ {":play_or_pause_button:", ":play or pause button:", "&#x23ef;"},
+ {":point_down:", ":backhand index pointing down:", "&#x1f447;"},
+ {":point_left:", ":backhand index pointing left:", "&#x1f448;"},
+ {":point_right:", ":backhand index pointing right:", "&#x1f449;"},
+ {":point_up:", ":index pointing up:", "&#x261d;"},
+ {":point_up_2:", ":backhand index pointing up:", "&#x1f446;"},
+ {":poland:", ":flag poland:", "&#x1f1f5;&#x1f1f1;"},
+ {":police_car:", ":police car:", "&#x1f693;"},
+ {":policeman:", ":police officer:", "&#x1f46e;"},
+ {":policewoman:", ":woman police officer:", "&#x1f46e;&#x200d;&#x2640;&#xfe0f;"},
+ {":poodle:", ":poodle:", "&#x1f429;"},
+ {":poop:", ":pile of poo:", "&#x1f4a9;"},
+ {":popcorn:", ":popcorn:", "&#x1f37f;"},
+ {":portugal:", ":flag portugal:", "&#x1f1f5;&#x1f1f9;"},
+ {":post_office:", ":japanese post office:", "&#x1f3e3;"},
+ {":postal_horn:", ":postal horn:", "&#x1f4ef;"},
+ {":postbox:", ":postbox:", "&#x1f4ee;"},
+ {":potable_water:", ":potable water:", "&#x1f6b0;"},
+ {":potato:", ":potato:", "&#x1f954;"},
+ {":pouch:", ":clutch bag:", "&#x1f45d;"},
+ {":poultry_leg:", ":poultry leg:", "&#x1f357;"},
+ {":pound:", ":pound banknote:", "&#x1f4b7;"},
+ {":pout:", ":pouting face:", "&#x1f621;"},
+ {":pouting_cat:", ":pouting cat face:", "&#x1f63e;"},
+ {":pouting_man:", ":man pouting:", "&#x1f64e;&#x200d;&#x2642;&#xfe0f;"},
+ {":pouting_woman:", ":person pouting:", "&#x1f64e;"},
+ {":pray:", ":folded hands:", "&#x1f64f;"},
+ {":prayer_beads:", ":prayer beads:", "&#x1f4ff;"},
+ {":pregnant_woman:", ":pregnant woman:", "&#x1f930;"},
+ {":previous_track_button:", ":last track button:", "&#x23ee;"},
+ {":prince:", ":prince:", "&#x1f934;"},
+ {":princess:", ":princess:", "&#x1f478;"},
+ {":printer:", ":printer:", "&#x1f5a8;"},
+ {":puerto_rico:", ":flag puerto rico:", "&#x1f1f5;&#x1f1f7;"},
+ {":punch:", ":oncoming fist:", "&#x1f44a;"},
+ {":purple_heart:", ":purple heart:", "&#x1f49c;"},
+ {":purse:", ":purse:", "&#x1f45b;"},
+ {":pushpin:", ":pushpin:", "&#x1f4cc;"},
+ {":put_litter_in_its_place:", ":litter in bin sign:", "&#x1f6ae;"},
+ {":qatar:", ":flag qatar:", "&#x1f1f6;&#x1f1e6;"},
+ {":question:", ":question mark:", "&#x2753;"},
+ {":rabbit:", ":rabbit face:", "&#x1f430;"},
+ {":rabbit2:", ":rabbit:", "&#x1f407;"},
+ {":racehorse:", ":horse:", "&#x1f40e;"},
+ {":racing_car:", ":racing car:", "&#x1f3ce;"},
+ {":radio:", ":radio:", "&#x1f4fb;"},
+ {":radio_button:", ":radio button:", "&#x1f518;"},
+ {":radioactive:", ":radioactive:", "&#x2622;"},
+ {":rage:", ":pouting face:", "&#x1f621;"},
+ {":railway_car:", ":railway car:", "&#x1f683;"},
+ {":railway_track:", ":railway track:", "&#x1f6e4;"},
+ {":rainbow:", ":rainbow:", "&#x1f308;"},
+ {":rainbow_flag:", ":rainbow flag:", "&#x1f3f3;&#xfe0f;&#x200d;&#x1f308;"},
+ {":raised_back_of_hand:", ":raised back of hand:", "&#x1f91a;"},
+ {":raised_hand:", ":raised hand:", "&#x270b;"},
+ {":raised_hand_with_fingers_splayed:", ":hand with fingers splayed:", "&#x1f590;"},
+ {":raised_hands:", ":raising hands:", "&#x1f64c;"},
+ {":raising_hand:", ":person raising hand:", "&#x1f64b;"},
+ {":raising_hand_man:", ":man raising hand:", "&#x1f64b;&#x200d;&#x2642;&#xfe0f;"},
+ {":raising_hand_woman:", ":person raising hand:", "&#x1f64b;"},
+ {":ram:", ":ram:", "&#x1f40f;"},
+ {":ramen:", ":steaming bowl:", "&#x1f35c;"},
+ {":rat:", ":rat:", "&#x1f400;"},
+ {":record_button:", ":record button:", "&#x23fa;"},
+ {":recycle:", ":recycling symbol:", "&#x267b;"},
+ {":red_car:", ":automobile:", "&#x1f697;"},
+ {":red_circle:", ":red circle:", "&#x1f534;"},
+ {":registered:", ":registered:", "&#x00ae;"},
+ {":relaxed:", ":smiling face:", "&#x263a;"},
+ {":relieved:", ":relieved face:", "&#x1f60c;"},
+ {":reminder_ribbon:", ":reminder ribbon:", "&#x1f397;"},
+ {":repeat:", ":repeat button:", "&#x1f501;"},
+ {":repeat_one:", ":repeat single button:", "&#x1f502;"},
+ {":rescue_worker_helmet:", ":rescue worker's helmet:", "&#x26d1;"},
+ {":restroom:", ":restroom:", "&#x1f6bb;"},
+ {":reunion:", ":flag réunion:", "&#x1f1f7;&#x1f1ea;"},
+ {":revolving_hearts:", ":revolving hearts:", "&#x1f49e;"},
+ {":rewind:", ":fast reverse button:", "&#x23ea;"},
+ {":rhinoceros:", ":rhinoceros:", "&#x1f98f;"},
+ {":ribbon:", ":ribbon:", "&#x1f380;"},
+ {":rice:", ":cooked rice:", "&#x1f35a;"},
+ {":rice_ball:", ":rice ball:", "&#x1f359;"},
+ {":rice_cracker:", ":rice cracker:", "&#x1f358;"},
+ {":rice_scene:", ":moon viewing ceremony:", "&#x1f391;"},
+ {":right_anger_bubble:", ":right anger bubble:", "&#x1f5ef;"},
+ {":ring:", ":ring:", "&#x1f48d;"},
+ {":robot:", ":robot face:", "&#x1f916;"},
+ {":rocket:", ":rocket:", "&#x1f680;"},
+ {":rofl:", ":rolling on the floor laughing:", "&#x1f923;"},
+ {":roll_eyes:", ":face with rolling eyes:", "&#x1f644;"},
+ {":roller_coaster:", ":roller coaster:", "&#x1f3a2;"},
+ {":romania:", ":flag romania:", "&#x1f1f7;&#x1f1f4;"},
+ {":rooster:", ":rooster:", "&#x1f413;"},
+ {":rose:", ":rose:", "&#x1f339;"},
+ {":rosette:", ":rosette:", "&#x1f3f5;"},
+ {":rotating_light:", ":police car light:", "&#x1f6a8;"},
+ {":round_pushpin:", ":round pushpin:", "&#x1f4cd;"},
+ {":rowboat:", ":person rowing boat:", "&#x1f6a3;"},
+ {":rowing_man:", ":person rowing boat:", "&#x1f6a3;"},
+ {":rowing_woman:", ":woman rowing boat:", "&#x1f6a3;&#x200d;&#x2640;&#xfe0f;"},
+ {":ru:", ":flag russia:", "&#x1f1f7;&#x1f1fa;"},
+ {":rugby_football:", ":rugby football:", "&#x1f3c9;"},
+ {":runner:", ":person running:", "&#x1f3c3;"},
+ {":running:", ":person running:", "&#x1f3c3;"},
+ {":running_man:", ":person running:", "&#x1f3c3;"},
+ {":running_shirt_with_sash:", ":running shirt:", "&#x1f3bd;"},
+ {":running_woman:", ":woman running:", "&#x1f3c3;&#x200d;&#x2640;&#xfe0f;"},
+ {":rwanda:", ":flag rwanda:", "&#x1f1f7;&#x1f1fc;"},
+ {":sa:", ":japanese \"service charge\" button:", "&#x1f202;"},
+ {":sagittarius:", ":sagittarius:", "&#x2650;"},
+ {":sailboat:", ":sailboat:", "&#x26f5;"},
+ {":sake:", ":sake:", "&#x1f376;"},
+ {":samoa:", ":flag samoa:", "&#x1f1fc;&#x1f1f8;"},
+ {":san_marino:", ":flag san marino:", "&#x1f1f8;&#x1f1f2;"},
+ {":sandal:", ":woman's sandal:", "&#x1f461;"},
+ {":santa:", ":santa claus:", "&#x1f385;"},
+ {":sao_tome_principe:", ":flag são tomé & príncipe:", "&#x1f1f8;&#x1f1f9;"},
+ {":satellite:", ":satellite antenna:", "&#x1f4e1;"},
+ {":satisfied:", ":grinning squinting face:", "&#x1f606;"},
+ {":saudi_arabia:", ":flag saudi arabia:", "&#x1f1f8;&#x1f1e6;"},
+ {":saxophone:", ":saxophone:", "&#x1f3b7;"},
+ {":school:", ":school:", "&#x1f3eb;"},
+ {":school_satchel:", ":backpack:", "&#x1f392;"},
+ {":scissors:", ":scissors:", "&#x2702;"},
+ {":scorpion:", ":scorpion:", "&#x1f982;"},
+ {":scorpius:", ":scorpio:", "&#x264f;"},
+ {":scream:", ":face screaming in fear:", "&#x1f631;"},
+ {":scream_cat:", ":weary cat face:", "&#x1f640;"},
+ {":scroll:", ":scroll:", "&#x1f4dc;"},
+ {":seat:", ":seat:", "&#x1f4ba;"},
+ {":secret:", ":japanese \"secret\" button:", "&#x3299;"},
+ {":see_no_evil:", ":see-no-evil monkey:", "&#x1f648;"},
+ {":seedling:", ":seedling:", "&#x1f331;"},
+ {":selfie:", ":selfie:", "&#x1f933;"},
+ {":senegal:", ":flag senegal:", "&#x1f1f8;&#x1f1f3;"},
+ {":serbia:", ":flag serbia:", "&#x1f1f7;&#x1f1f8;"},
+ {":seven:", ":keycap 7:", "&#x0037;&#xfe0f;&#x20e3;"},
+ {":seychelles:", ":flag seychelles:", "&#x1f1f8;&#x1f1e8;"},
+ {":shallow_pan_of_food:", ":shallow pan of food:", "&#x1f958;"},
+ {":shamrock:", ":shamrock:", "&#x2618;"},
+ {":shark:", ":shark:", "&#x1f988;"},
+ {":shaved_ice:", ":shaved ice:", "&#x1f367;"},
+ {":sheep:", ":ewe:", "&#x1f411;"},
+ {":shell:", ":spiral shell:", "&#x1f41a;"},
+ {":shield:", ":shield:", "&#x1f6e1;"},
+ {":shinto_shrine:", ":shinto shrine:", "&#x26e9;"},
+ {":ship:", ":ship:", "&#x1f6a2;"},
+ {":shirt:", ":t-shirt:", "&#x1f455;"},
+ {":shit:", ":pile of poo:", "&#x1f4a9;"},
+ {":shoe:", ":man's shoe:", "&#x1f45e;"},
+ {":shopping:", ":shopping bags:", "&#x1f6cd;"},
+ {":shopping_cart:", ":shopping cart:", "&#x1f6d2;"},
+ {":shower:", ":shower:", "&#x1f6bf;"},
+ {":shrimp:", ":shrimp:", "&#x1f990;"},
+ {":sierra_leone:", ":flag sierra leone:", "&#x1f1f8;&#x1f1f1;"},
+ {":signal_strength:", ":antenna bars:", "&#x1f4f6;"},
+ {":singapore:", ":flag singapore:", "&#x1f1f8;&#x1f1ec;"},
+ {":sint_maarten:", ":flag sint maarten:", "&#x1f1f8;&#x1f1fd;"},
+ {":six:", ":keycap 6:", "&#x0036;&#xfe0f;&#x20e3;"},
+ {":six_pointed_star:", ":dotted six-pointed star:", "&#x1f52f;"},
+ {":ski:", ":skis:", "&#x1f3bf;"},
+ {":skier:", ":skier:", "&#x26f7;"},
+ {":skull:", ":skull:", "&#x1f480;"},
+ {":skull_and_crossbones:", ":skull and crossbones:", "&#x2620;"},
+ {":sleeping:", ":sleeping face:", "&#x1f634;"},
+ {":sleeping_bed:", ":person in bed:", "&#x1f6cc;"},
+ {":sleepy:", ":sleepy face:", "&#x1f62a;"},
+ {":slightly_frowning_face:", ":slightly frowning face:", "&#x1f641;"},
+ {":slightly_smiling_face:", ":slightly smiling face:", "&#x1f642;"},
+ {":slot_machine:", ":slot machine:", "&#x1f3b0;"},
+ {":slovakia:", ":flag slovakia:", "&#x1f1f8;&#x1f1f0;"},
+ {":slovenia:", ":flag slovenia:", "&#x1f1f8;&#x1f1ee;"},
+ {":small_airplane:", ":small airplane:", "&#x1f6e9;"},
+ {":small_blue_diamond:", ":small blue diamond:", "&#x1f539;"},
+ {":small_orange_diamond:", ":small orange diamond:", "&#x1f538;"},
+ {":small_red_triangle:", ":red triangle pointed up:", "&#x1f53a;"},
+ {":small_red_triangle_down:", ":red triangle pointed down:", "&#x1f53b;"},
+ {":smile:", ":grinning face with smiling eyes:", "&#x1f604;"},
+ {":smile_cat:", ":grinning cat face with smiling eyes:", "&#x1f638;"},
+ {":smiley:", ":grinning face with big eyes:", "&#x1f603;"},
+ {":smiley_cat:", ":grinning cat face:", "&#x1f63a;"},
+ {":smiling_imp:", ":smiling face with horns:", "&#x1f608;"},
+ {":smirk:", ":smirking face:", "&#x1f60f;"},
+ {":smirk_cat:", ":cat face with wry smile:", "&#x1f63c;"},
+ {":smoking:", ":cigarette:", "&#x1f6ac;"},
+ {":snail:", ":snail:", "&#x1f40c;"},
+ {":snake:", ":snake:", "&#x1f40d;"},
+ {":sneezing_face:", ":sneezing face:", "&#x1f927;"},
+ {":snowboarder:", ":snowboarder:", "&#x1f3c2;"},
+ {":snowflake:", ":snowflake:", "&#x2744;"},
+ {":snowman:", ":snowman without snow:", "&#x26c4;"},
+ {":snowman_with_snow:", ":snowman:", "&#x2603;"},
+ {":sob:", ":loudly crying face:", "&#x1f62d;"},
+ {":soccer:", ":soccer ball:", "&#x26bd;"},
+ {":solomon_islands:", ":flag solomon islands:", "&#x1f1f8;&#x1f1e7;"},
+ {":somalia:", ":flag somalia:", "&#x1f1f8;&#x1f1f4;"},
+ {":soon:", ":soon arrow:", "&#x1f51c;"},
+ {":sos:", ":sos button:", "&#x1f198;"},
+ {":sound:", ":speaker medium volume:", "&#x1f509;"},
+ {":south_africa:", ":flag south africa:", "&#x1f1ff;&#x1f1e6;"},
+ {":south_georgia_south_sandwich_islands:", ":flag south georgia & south sandwich islands:", "&#x1f1ec;&#x1f1f8;"},
+ {":south_sudan:", ":flag south sudan:", "&#x1f1f8;&#x1f1f8;"},
+ {":space_invader:", ":alien monster:", "&#x1f47e;"},
+ {":spades:", ":spade suit:", "&#x2660;"},
+ {":spaghetti:", ":spaghetti:", "&#x1f35d;"},
+ {":sparkle:", ":sparkle:", "&#x2747;"},
+ {":sparkler:", ":sparkler:", "&#x1f387;"},
+ {":sparkles:", ":sparkles:", "&#x2728;"},
+ {":sparkling_heart:", ":sparkling heart:", "&#x1f496;"},
+ {":speak_no_evil:", ":speak-no-evil monkey:", "&#x1f64a;"},
+ {":speaker:", ":speaker low volume:", "&#x1f508;"},
+ {":speaking_head:", ":speaking head:", "&#x1f5e3;"},
+ {":speech_balloon:", ":speech balloon:", "&#x1f4ac;"},
+ {":speedboat:", ":speedboat:", "&#x1f6a4;"},
+ {":spider:", ":spider:", "&#x1f577;"},
+ {":spider_web:", ":spider web:", "&#x1f578;"},
+ {":spiral_calendar:", ":spiral calendar:", "&#x1f5d3;"},
+ {":spiral_notepad:", ":spiral notepad:", "&#x1f5d2;"},
+ {":spoon:", ":spoon:", "&#x1f944;"},
+ {":squid:", ":squid:", "&#x1f991;"},
+ {":sri_lanka:", ":flag sri lanka:", "&#x1f1f1;&#x1f1f0;"},
+ {":st_barthelemy:", ":flag st. barthélemy:", "&#x1f1e7;&#x1f1f1;"},
+ {":st_helena:", ":flag st. helena:", "&#x1f1f8;&#x1f1ed;"},
+ {":st_kitts_nevis:", ":flag st. kitts & nevis:", "&#x1f1f0;&#x1f1f3;"},
+ {":st_lucia:", ":flag st. lucia:", "&#x1f1f1;&#x1f1e8;"},
+ {":st_pierre_miquelon:", ":flag st. pierre & miquelon:", "&#x1f1f5;&#x1f1f2;"},
+ {":st_vincent_grenadines:", ":flag st. vincent & grenadines:", "&#x1f1fb;&#x1f1e8;"},
+ {":stadium:", ":stadium:", "&#x1f3df;"},
+ {":star:", ":star:", "&#x2b50;"},
+ {":star2:", ":glowing star:", "&#x1f31f;"},
+ {":star_and_crescent:", ":star and crescent:", "&#x262a;"},
+ {":star_of_david:", ":star of david:", "&#x2721;"},
+ {":stars:", ":shooting star:", "&#x1f320;"},
+ {":station:", ":station:", "&#x1f689;"},
+ {":statue_of_liberty:", ":statue of liberty:", "&#x1f5fd;"},
+ {":steam_locomotive:", ":locomotive:", "&#x1f682;"},
+ {":stew:", ":pot of food:", "&#x1f372;"},
+ {":stop_button:", ":stop button:", "&#x23f9;"},
+ {":stop_sign:", ":stop sign:", "&#x1f6d1;"},
+ {":stopwatch:", ":stopwatch:", "&#x23f1;"},
+ {":straight_ruler:", ":straight ruler:", "&#x1f4cf;"},
+ {":strawberry:", ":strawberry:", "&#x1f353;"},
+ {":stuck_out_tongue:", ":face with tongue:", "&#x1f61b;"},
+ {":stuck_out_tongue_closed_eyes:", ":squinting face with tongue:", "&#x1f61d;"},
+ {":stuck_out_tongue_winking_eye:", ":winking face with tongue:", "&#x1f61c;"},
+ {":studio_microphone:", ":studio microphone:", "&#x1f399;"},
+ {":stuffed_flatbread:", ":stuffed flatbread:", "&#x1f959;"},
+ {":sudan:", ":flag sudan:", "&#x1f1f8;&#x1f1e9;"},
+ {":sun_behind_large_cloud:", ":sun behind large cloud:", "&#x1f325;"},
+ {":sun_behind_rain_cloud:", ":sun behind rain cloud:", "&#x1f326;"},
+ {":sun_behind_small_cloud:", ":sun behind small cloud:", "&#x1f324;"},
+ {":sun_with_face:", ":sun with face:", "&#x1f31e;"},
+ {":sunflower:", ":sunflower:", "&#x1f33b;"},
+ {":sunglasses:", ":smiling face with sunglasses:", "&#x1f60e;"},
+ {":sunny:", ":sun:", "&#x2600;"},
+ {":sunrise:", ":sunrise:", "&#x1f305;"},
+ {":sunrise_over_mountains:", ":sunrise over mountains:", "&#x1f304;"},
+ {":surfer:", ":person surfing:", "&#x1f3c4;"},
+ {":surfing_man:", ":person surfing:", "&#x1f3c4;"},
+ {":surfing_woman:", ":woman surfing:", "&#x1f3c4;&#x200d;&#x2640;&#xfe0f;"},
+ {":suriname:", ":flag suriname:", "&#x1f1f8;&#x1f1f7;"},
+ {":sushi:", ":sushi:", "&#x1f363;"},
+ {":suspension_railway:", ":suspension railway:", "&#x1f69f;"},
+ {":swaziland:", ":flag swaziland:", "&#x1f1f8;&#x1f1ff;"},
+ {":sweat:", ":downcast face with sweat:", "&#x1f613;"},
+ {":sweat_drops:", ":sweat droplets:", "&#x1f4a6;"},
+ {":sweat_smile:", ":grinning face with sweat:", "&#x1f605;"},
+ {":sweden:", ":flag sweden:", "&#x1f1f8;&#x1f1ea;"},
+ {":sweet_potato:", ":roasted sweet potato:", "&#x1f360;"},
+ {":swimmer:", ":person swimming:", "&#x1f3ca;"},
+ {":swimming_man:", ":person swimming:", "&#x1f3ca;"},
+ {":swimming_woman:", ":woman swimming:", "&#x1f3ca;&#x200d;&#x2640;&#xfe0f;"},
+ {":switzerland:", ":flag switzerland:", "&#x1f1e8;&#x1f1ed;"},
+ {":symbols:", ":input symbols:", "&#x1f523;"},
+ {":synagogue:", ":synagogue:", "&#x1f54d;"},
+ {":syria:", ":flag syria:", "&#x1f1f8;&#x1f1fe;"},
+ {":syringe:", ":syringe:", "&#x1f489;"},
+ {":taco:", ":taco:", "&#x1f32e;"},
+ {":tada:", ":party popper:", "&#x1f389;"},
+ {":taiwan:", ":flag taiwan:", "&#x1f1f9;&#x1f1fc;"},
+ {":tajikistan:", ":flag tajikistan:", "&#x1f1f9;&#x1f1ef;"},
+ {":tanabata_tree:", ":tanabata tree:", "&#x1f38b;"},
+ {":tangerine:", ":tangerine:", "&#x1f34a;"},
+ {":tanzania:", ":flag tanzania:", "&#x1f1f9;&#x1f1ff;"},
+ {":taurus:", ":taurus:", "&#x2649;"},
+ {":taxi:", ":taxi:", "&#x1f695;"},
+ {":tea:", ":teacup without handle:", "&#x1f375;"},
+ {":telephone:", ":telephone:", "&#x260e;"},
+ {":telephone_receiver:", ":telephone receiver:", "&#x1f4de;"},
+ {":telescope:", ":telescope:", "&#x1f52d;"},
+ {":tennis:", ":tennis:", "&#x1f3be;"},
+ {":tent:", ":tent:", "&#x26fa;"},
+ {":thailand:", ":flag thailand:", "&#x1f1f9;&#x1f1ed;"},
+ {":thermometer:", ":thermometer:", "&#x1f321;"},
+ {":thinking:", ":thinking face:", "&#x1f914;"},
+ {":thought_balloon:", ":thought balloon:", "&#x1f4ad;"},
+ {":three:", ":keycap 3:", "&#x0033;&#xfe0f;&#x20e3;"},
+ {":thumbsdown:", ":thumbs down:", "&#x1f44e;"},
+ {":thumbsup:", ":thumbs up:", "&#x1f44d;"},
+ {":ticket:", ":ticket:", "&#x1f3ab;"},
+ {":tickets:", ":admission tickets:", "&#x1f39f;"},
+ {":tiger:", ":tiger face:", "&#x1f42f;"},
+ {":tiger2:", ":tiger:", "&#x1f405;"},
+ {":timer_clock:", ":timer clock:", "&#x23f2;"},
+ {":timor_leste:", ":flag timor-leste:", "&#x1f1f9;&#x1f1f1;"},
+ {":tipping_hand_man:", ":man tipping hand:", "&#x1f481;&#x200d;&#x2642;&#xfe0f;"},
+ {":tipping_hand_woman:", ":person tipping hand:", "&#x1f481;"},
+ {":tired_face:", ":tired face:", "&#x1f62b;"},
+ {":tm:", ":trade mark:", "&#x2122;"},
+ {":togo:", ":flag togo:", "&#x1f1f9;&#x1f1ec;"},
+ {":toilet:", ":toilet:", "&#x1f6bd;"},
+ {":tokelau:", ":flag tokelau:", "&#x1f1f9;&#x1f1f0;"},
+ {":tokyo_tower:", ":tokyo tower:", "&#x1f5fc;"},
+ {":tomato:", ":tomato:", "&#x1f345;"},
+ {":tonga:", ":flag tonga:", "&#x1f1f9;&#x1f1f4;"},
+ {":tongue:", ":tongue:", "&#x1f445;"},
+ {":top:", ":top arrow:", "&#x1f51d;"},
+ {":tophat:", ":top hat:", "&#x1f3a9;"},
+ {":tornado:", ":tornado:", "&#x1f32a;"},
+ {":tr:", ":flag turkey:", "&#x1f1f9;&#x1f1f7;"},
+ {":trackball:", ":trackball:", "&#x1f5b2;"},
+ {":tractor:", ":tractor:", "&#x1f69c;"},
+ {":traffic_light:", ":horizontal traffic light:", "&#x1f6a5;"},
+ {":train:", ":tram car:", "&#x1f68b;"},
+ {":train2:", ":train:", "&#x1f686;"},
+ {":tram:", ":tram:", "&#x1f68a;"},
+ {":triangular_flag_on_post:", ":triangular flag:", "&#x1f6a9;"},
+ {":triangular_ruler:", ":triangular ruler:", "&#x1f4d0;"},
+ {":trident:", ":trident emblem:", "&#x1f531;"},
+ {":trinidad_tobago:", ":flag trinidad & tobago:", "&#x1f1f9;&#x1f1f9;"},
+ {":triumph:", ":face with steam from nose:", "&#x1f624;"},
+ {":trolleybus:", ":trolleybus:", "&#x1f68e;"},
+ {":trophy:", ":trophy:", "&#x1f3c6;"},
+ {":tropical_drink:", ":tropical drink:", "&#x1f379;"},
+ {":tropical_fish:", ":tropical fish:", "&#x1f420;"},
+ {":truck:", ":delivery truck:", "&#x1f69a;"},
+ {":trumpet:", ":trumpet:", "&#x1f3ba;"},
+ {":tshirt:", ":t-shirt:", "&#x1f455;"},
+ {":tulip:", ":tulip:", "&#x1f337;"},
+ {":tumbler_glass:", ":tumbler glass:", "&#x1f943;"},
+ {":tunisia:", ":flag tunisia:", "&#x1f1f9;&#x1f1f3;"},
+ {":turkey:", ":turkey:", "&#x1f983;"},
+ {":turkmenistan:", ":flag turkmenistan:", "&#x1f1f9;&#x1f1f2;"},
+ {":turks_caicos_islands:", ":flag turks & caicos islands:", "&#x1f1f9;&#x1f1e8;"},
+ {":turtle:", ":turtle:", "&#x1f422;"},
+ {":tuvalu:", ":flag tuvalu:", "&#x1f1f9;&#x1f1fb;"},
+ {":tv:", ":television:", "&#x1f4fa;"},
+ {":twisted_rightwards_arrows:", ":shuffle tracks button:", "&#x1f500;"},
+ {":two:", ":keycap 2:", "&#x0032;&#xfe0f;&#x20e3;"},
+ {":two_hearts:", ":two hearts:", "&#x1f495;"},
+ {":two_men_holding_hands:", ":two men holding hands:", "&#x1f46c;"},
+ {":two_women_holding_hands:", ":two women holding hands:", "&#x1f46d;"},
+ {":u5272:", ":japanese \"discount\" button:", "&#x1f239;"},
+ {":u5408:", ":japanese \"passing grade\" button:", "&#x1f234;"},
+ {":u55b6:", ":japanese \"open for business\" button:", "&#x1f23a;"},
+ {":u6307:", ":japanese \"reserved\" button:", "&#x1f22f;"},
+ {":u6708:", ":japanese \"monthly amount\" button:", "&#x1f237;"},
+ {":u6709:", ":japanese \"not free of charge\" button:", "&#x1f236;"},
+ {":u6e80:", ":japanese \"no vacancy\" button:", "&#x1f235;"},
+ {":u7121:", ":japanese \"free of charge\" button:", "&#x1f21a;"},
+ {":u7533:", ":japanese \"application\" button:", "&#x1f238;"},
+ {":u7981:", ":japanese \"prohibited\" button:", "&#x1f232;"},
+ {":u7a7a:", ":japanese \"vacancy\" button:", "&#x1f233;"},
+ {":uganda:", ":flag uganda:", "&#x1f1fa;&#x1f1ec;"},
+ {":uk:", ":flag united kingdom:", "&#x1f1ec;&#x1f1e7;"},
+ {":ukraine:", ":flag ukraine:", "&#x1f1fa;&#x1f1e6;"},
+ {":umbrella:", ":umbrella with rain drops:", "&#x2614;"},
+ {":unamused:", ":unamused face:", "&#x1f612;"},
+ {":underage:", ":no one under eighteen:", "&#x1f51e;"},
+ {":unicorn:", ":unicorn face:", "&#x1f984;"},
+ {":united_arab_emirates:", ":flag united arab emirates:", "&#x1f1e6;&#x1f1ea;"},
+ {":unlock:", ":unlocked:", "&#x1f513;"},
+ {":up:", ":up! button:", "&#x1f199;"},
+ {":upside_down_face:", ":upside-down face:", "&#x1f643;"},
+ {":uruguay:", ":flag uruguay:", "&#x1f1fa;&#x1f1fe;"},
+ {":us:", ":flag united states:", "&#x1f1fa;&#x1f1f8;"},
+ {":us_virgin_islands:", ":flag u.s. virgin islands:", "&#x1f1fb;&#x1f1ee;"},
+ {":uzbekistan:", ":flag uzbekistan:", "&#x1f1fa;&#x1f1ff;"},
+ {":v:", ":victory hand:", "&#x270c;"},
+ {":vanuatu:", ":flag vanuatu:", "&#x1f1fb;&#x1f1fa;"},
+ {":vatican_city:", ":flag vatican city:", "&#x1f1fb;&#x1f1e6;"},
+ {":venezuela:", ":flag venezuela:", "&#x1f1fb;&#x1f1ea;"},
+ {":vertical_traffic_light:", ":vertical traffic light:", "&#x1f6a6;"},
+ {":vhs:", ":videocassette:", "&#x1f4fc;"},
+ {":vibration_mode:", ":vibration mode:", "&#x1f4f3;"},
+ {":video_camera:", ":video camera:", "&#x1f4f9;"},
+ {":video_game:", ":video game:", "&#x1f3ae;"},
+ {":vietnam:", ":flag vietnam:", "&#x1f1fb;&#x1f1f3;"},
+ {":violin:", ":violin:", "&#x1f3bb;"},
+ {":virgo:", ":virgo:", "&#x264d;"},
+ {":volcano:", ":volcano:", "&#x1f30b;"},
+ {":volleyball:", ":volleyball:", "&#x1f3d0;"},
+ {":vs:", ":vs button:", "&#x1f19a;"},
+ {":vulcan_salute:", ":vulcan salute:", "&#x1f596;"},
+ {":walking:", ":person walking:", "&#x1f6b6;"},
+ {":walking_man:", ":person walking:", "&#x1f6b6;"},
+ {":walking_woman:", ":woman walking:", "&#x1f6b6;&#x200d;&#x2640;&#xfe0f;"},
+ {":wallis_futuna:", ":flag wallis & futuna:", "&#x1f1fc;&#x1f1eb;"},
+ {":waning_crescent_moon:", ":waning crescent moon:", "&#x1f318;"},
+ {":waning_gibbous_moon:", ":waning gibbous moon:", "&#x1f316;"},
+ {":warning:", ":warning:", "&#x26a0;"},
+ {":wastebasket:", ":wastebasket:", "&#x1f5d1;"},
+ {":watch:", ":watch:", "&#x231a;"},
+ {":water_buffalo:", ":water buffalo:", "&#x1f403;"},
+ {":watermelon:", ":watermelon:", "&#x1f349;"},
+ {":wave:", ":waving hand:", "&#x1f44b;"},
+ {":wavy_dash:", ":wavy dash:", "&#x3030;"},
+ {":waxing_crescent_moon:", ":waxing crescent moon:", "&#x1f312;"},
+ {":waxing_gibbous_moon:", ":waxing gibbous moon:", "&#x1f314;"},
+ {":wc:", ":water closet:", "&#x1f6be;"},
+ {":weary:", ":weary face:", "&#x1f629;"},
+ {":wedding:", ":wedding:", "&#x1f492;"},
+ {":weight_lifting_man:", ":person lifting weights:", "&#x1f3cb;"},
+ {":weight_lifting_woman:", ":woman lifting weights:", "&#x1f3cb;&#xfe0f;&#x200d;&#x2640;&#xfe0f;"},
+ {":western_sahara:", ":flag western sahara:", "&#x1f1ea;&#x1f1ed;"},
+ {":whale:", ":spouting whale:", "&#x1f433;"},
+ {":whale2:", ":whale:", "&#x1f40b;"},
+ {":wheel_of_dharma:", ":wheel of dharma:", "&#x2638;"},
+ {":wheelchair:", ":wheelchair symbol:", "&#x267f;"},
+ {":white_check_mark:", ":white heavy check mark:", "&#x2705;"},
+ {":white_circle:", ":white circle:", "&#x26aa;"},
+ {":white_flag:", ":white flag:", "&#x1f3f3;"},
+ {":white_flower:", ":white flower:", "&#x1f4ae;"},
+ {":white_large_square:", ":white large square:", "&#x2b1c;"},
+ {":white_medium_small_square:", ":white medium-small square:", "&#x25fd;"},
+ {":white_medium_square:", ":white medium square:", "&#x25fb;"},
+ {":white_small_square:", ":white small square:", "&#x25ab;"},
+ {":white_square_button:", ":white square button:", "&#x1f533;"},
+ {":wilted_flower:", ":wilted flower:", "&#x1f940;"},
+ {":wind_chime:", ":wind chime:", "&#x1f390;"},
+ {":wind_face:", ":wind face:", "&#x1f32c;"},
+ {":wine_glass:", ":wine glass:", "&#x1f377;"},
+ {":wink:", ":winking face:", "&#x1f609;"},
+ {":wolf:", ":wolf face:", "&#x1f43a;"},
+ {":woman:", ":woman:", "&#x1f469;"},
+ {":woman_artist:", ":woman artist:", "&#x1f469;&#x200d;&#x1f3a8;"},
+ {":woman_astronaut:", ":woman astronaut:", "&#x1f469;&#x200d;&#x1f680;"},
+ {":woman_cartwheeling:", ":woman cartwheeling:", "&#x1f938;&#x200d;&#x2640;&#xfe0f;"},
+ {":woman_cook:", ":woman cook:", "&#x1f469;&#x200d;&#x1f373;"},
+ {":woman_facepalming:", ":woman facepalming:", "&#x1f926;&#x200d;&#x2640;&#xfe0f;"},
+ {":woman_factory_worker:", ":woman factory worker:", "&#x1f469;&#x200d;&#x1f3ed;"},
+ {":woman_farmer:", ":woman farmer:", "&#x1f469;&#x200d;&#x1f33e;"},
+ {":woman_firefighter:", ":woman firefighter:", "&#x1f469;&#x200d;&#x1f692;"},
+ {":woman_health_worker:", ":woman health worker:", "&#x1f469;&#x200d;&#x2695;&#xfe0f;"},
+ {":woman_judge:", ":woman judge:", "&#x1f469;&#x200d;&#x2696;&#xfe0f;"},
+ {":woman_juggling:", ":woman juggling:", "&#x1f939;&#x200d;&#x2640;&#xfe0f;"},
+ {":woman_mechanic:", ":woman mechanic:", "&#x1f469;&#x200d;&#x1f527;"},
+ {":woman_office_worker:", ":woman office worker:", "&#x1f469;&#x200d;&#x1f4bc;"},
+ {":woman_pilot:", ":woman pilot:", "&#x1f469;&#x200d;&#x2708;&#xfe0f;"},
+ {":woman_playing_handball:", ":woman playing handball:", "&#x1f93e;&#x200d;&#x2640;&#xfe0f;"},
+ {":woman_playing_water_polo:", ":woman playing water polo:", "&#x1f93d;&#x200d;&#x2640;&#xfe0f;"},
+ {":woman_scientist:", ":woman scientist:", "&#x1f469;&#x200d;&#x1f52c;"},
+ {":woman_shrugging:", ":woman shrugging:", "&#x1f937;&#x200d;&#x2640;&#xfe0f;"},
+ {":woman_singer:", ":woman singer:", "&#x1f469;&#x200d;&#x1f3a4;"},
+ {":woman_student:", ":woman student:", "&#x1f469;&#x200d;&#x1f393;"},
+ {":woman_teacher:", ":woman teacher:", "&#x1f469;&#x200d;&#x1f3eb;"},
+ {":woman_technologist:", ":woman technologist:", "&#x1f469;&#x200d;&#x1f4bb;"},
+ {":woman_with_turban:", ":woman wearing turban:", "&#x1f473;&#x200d;&#x2640;&#xfe0f;"},
+ {":womans_clothes:", ":woman's clothes:", "&#x1f45a;"},
+ {":womans_hat:", ":woman's hat:", "&#x1f452;"},
+ {":women_wrestling:", ":women wrestling:", "&#x1f93c;&#x200d;&#x2640;&#xfe0f;"},
+ {":womens:", ":women's room:", "&#x1f6ba;"},
+ {":world_map:", ":world map:", "&#x1f5fa;"},
+ {":worried:", ":worried face:", "&#x1f61f;"},
+ {":wrench:", ":wrench:", "&#x1f527;"},
+ {":writing_hand:", ":writing hand:", "&#x270d;"},
+ {":x:", ":cross mark:", "&#x274c;"},
+ {":yellow_heart:", ":yellow heart:", "&#x1f49b;"},
+ {":yemen:", ":flag yemen:", "&#x1f1fe;&#x1f1ea;"},
+ {":yen:", ":yen banknote:", "&#x1f4b4;"},
+ {":yin_yang:", ":yin yang:", "&#x262f;"},
+ {":yum:", ":face savoring food:", "&#x1f60b;"},
+ {":zambia:", ":flag zambia:", "&#x1f1ff;&#x1f1f2;"},
+ {":zap:", ":high voltage:", "&#x26a1;"},
+ {":zero:", ":keycap 0:", "&#x0030;&#xfe0f;&#x20e3;"},
+ {":zimbabwe:", ":flag zimbabwe:", "&#x1f1ff;&#x1f1fc;"},
+ {":zipper_mouth_face:", ":zipper-mouth face:", "&#x1f910;"},
+ {":zzz:", ":zzz:", "&#x1f4a4;"},
+ {"", ":smiling face with 3 hearts:", "&#x1f970;"},
+ {"", ":star-struck:", "&#x1f929;"},
+ {"", ":zany face:", "&#x1f92a;"},
+ {"", ":face with hand over mouth:", "&#x1f92d;"},
+ {"", ":shushing face:", "&#x1f92b;"},
+ {"", ":face with raised eyebrow:", "&#x1f928;"},
+ {"", ":face vomiting:", "&#x1f92e;"},
+ {"", ":hot face:", "&#x1f975;"},
+ {"", ":cold face:", "&#x1f976;"},
+ {"", ":woozy face:", "&#x1f974;"},
+ {"", ":exploding head:", "&#x1f92f;"},
+ {"", ":partying face:", "&#x1f973;"},
+ {"", ":face with monocle:", "&#x1f9d0;"},
+ {"", ":pleading face:", "&#x1f97a;"},
+ {"", ":face with symbols on mouth:", "&#x1f92c;"},
+ {"", ":orange heart:", "&#x1f9e1;"},
+ {"", ":left speech bubble:", "&#x1f5e8;"},
+ {"", ":love-you gesture:", "&#x1f91f;"},
+ {"", ":palms up together:", "&#x1f932;"},
+ {"", ":leg:", "&#x1f9b5;"},
+ {"", ":foot:", "&#x1f9b6;"},
+ {"", ":brain:", "&#x1f9e0;"},
+ {"", ":tooth:", "&#x1f9b7;"},
+ {"", ":bone:", "&#x1f9b4;"},
+ {"", ":eye:", "&#x1f441;"},
+ {"", ":child:", "&#x1f9d2;"},
+ {"", ":person:", "&#x1f9d1;"},
+ {"", ":man blond hair:", "&#x1f471;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man red hair:", "&#x1f468;&#x200d;&#x1f9b0;"},
+ {"", ":man curly hair:", "&#x1f468;&#x200d;&#x1f9b1;"},
+ {"", ":man white hair:", "&#x1f468;&#x200d;&#x1f9b3;"},
+ {"", ":man bald:", "&#x1f468;&#x200d;&#x1f9b2;"},
+ {"", ":man beard:", "&#x1f9d4;"},
+ {"", ":woman red hair:", "&#x1f469;&#x200d;&#x1f9b0;"},
+ {"", ":woman curly hair:", "&#x1f469;&#x200d;&#x1f9b1;"},
+ {"", ":woman white hair:", "&#x1f469;&#x200d;&#x1f9b3;"},
+ {"", ":woman bald:", "&#x1f469;&#x200d;&#x1f9b2;"},
+ {"", ":older person:", "&#x1f9d3;"},
+ {"", ":woman frowning:", "&#x1f64d;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman pouting:", "&#x1f64e;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman gesturing no:", "&#x1f645;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman gesturing ok:", "&#x1f646;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman tipping hand:", "&#x1f481;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman raising hand:", "&#x1f64b;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":man bowing:", "&#x1f647;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":person facepalming:", "&#x1f926;"},
+ {"", ":person shrugging:", "&#x1f937;"},
+ {"", ":man police officer:", "&#x1f46e;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man detective:", "&#x1f575;&#xfe0f;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man guard:", "&#x1f482;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man construction worker:", "&#x1f477;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man wearing turban:", "&#x1f473;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman with headscarf:", "&#x1f9d5;"},
+ {"", ":breast-feeding:", "&#x1f931;"},
+ {"", ":superhero:", "&#x1f9b8;"},
+ {"", ":man superhero:", "&#x1f9b8;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman superhero:", "&#x1f9b8;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":supervillain:", "&#x1f9b9;"},
+ {"", ":man supervillain:", "&#x1f9b9;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman supervillain:", "&#x1f9b9;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":mage:", "&#x1f9d9;"},
+ {"", ":man mage:", "&#x1f9d9;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman mage:", "&#x1f9d9;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":fairy:", "&#x1f9da;"},
+ {"", ":man fairy:", "&#x1f9da;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman fairy:", "&#x1f9da;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":vampire:", "&#x1f9db;"},
+ {"", ":man vampire:", "&#x1f9db;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman vampire:", "&#x1f9db;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":merperson:", "&#x1f9dc;"},
+ {"", ":merman:", "&#x1f9dc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":mermaid:", "&#x1f9dc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":elf:", "&#x1f9dd;"},
+ {"", ":man elf:", "&#x1f9dd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman elf:", "&#x1f9dd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":genie:", "&#x1f9de;"},
+ {"", ":man genie:", "&#x1f9de;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman genie:", "&#x1f9de;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":zombie:", "&#x1f9df;"},
+ {"", ":man zombie:", "&#x1f9df;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman zombie:", "&#x1f9df;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman getting massage:", "&#x1f486;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman getting haircut:", "&#x1f487;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":man walking:", "&#x1f6b6;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man running:", "&#x1f3c3;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":women with bunny ears:", "&#x1f46f;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person in steamy room:", "&#x1f9d6;"},
+ {"", ":man in steamy room:", "&#x1f9d6;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman in steamy room:", "&#x1f9d6;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person climbing:", "&#x1f9d7;"},
+ {"", ":man climbing:", "&#x1f9d7;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman climbing:", "&#x1f9d7;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":man golfing:", "&#x1f3cc;&#xfe0f;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man surfing:", "&#x1f3c4;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man rowing boat:", "&#x1f6a3;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man swimming:", "&#x1f3ca;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man bouncing ball:", "&#x26f9;&#xfe0f;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man lifting weights:", "&#x1f3cb;&#xfe0f;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man biking:", "&#x1f6b4;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man mountain biking:", "&#x1f6b5;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":person cartwheeling:", "&#x1f938;"},
+ {"", ":people wrestling:", "&#x1f93c;"},
+ {"", ":person playing water polo:", "&#x1f93d;"},
+ {"", ":person playing handball:", "&#x1f93e;"},
+ {"", ":person juggling:", "&#x1f939;"},
+ {"", ":person in lotus position:", "&#x1f9d8;"},
+ {"", ":man in lotus position:", "&#x1f9d8;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman in lotus position:", "&#x1f9d8;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":kiss woman, man:", "&#x1f469;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f468;"},
+ {"", ":couple with heart woman, man:", "&#x1f469;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f468;"},
+ {"", ":couple with heart man, man:", "&#x1f468;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f468;"},
+ {"", ":couple with heart woman, woman:", "&#x1f469;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f469;"},
+ {"", ":family man, boy:", "&#x1f468;&#x200d;&#x1f466;"},
+ {"", ":family man, boy, boy:", "&#x1f468;&#x200d;&#x1f466;&#x200d;&#x1f466;"},
+ {"", ":family man, girl:", "&#x1f468;&#x200d;&#x1f467;"},
+ {"", ":family man, girl, boy:", "&#x1f468;&#x200d;&#x1f467;&#x200d;&#x1f466;"},
+ {"", ":family man, girl, girl:", "&#x1f468;&#x200d;&#x1f467;&#x200d;&#x1f467;"},
+ {"", ":family woman, boy:", "&#x1f469;&#x200d;&#x1f466;"},
+ {"", ":family woman, boy, boy:", "&#x1f469;&#x200d;&#x1f466;&#x200d;&#x1f466;"},
+ {"", ":family woman, girl:", "&#x1f469;&#x200d;&#x1f467;"},
+ {"", ":family woman, girl, boy:", "&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f466;"},
+ {"", ":family woman, girl, girl:", "&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f467;"},
+ {"", ":red hair:", "&#x1f9b0;"},
+ {"", ":curly hair:", "&#x1f9b1;"},
+ {"", ":white hair:", "&#x1f9b3;"},
+ {"", ":bald:", "&#x1f9b2;"},
+ {"", ":female sign:", "&#x2640;"},
+ {"", ":male sign:", "&#x2642;"},
+ {"", ":raccoon:", "&#x1f99d;"},
+ {"", ":zebra:", "&#x1f993;"},
+ {"", ":llama:", "&#x1f999;"},
+ {"", ":giraffe:", "&#x1f992;"},
+ {"", ":hippopotamus:", "&#x1f99b;"},
+ {"", ":hedgehog:", "&#x1f994;"},
+ {"", ":kangaroo:", "&#x1f998;"},
+ {"", ":badger:", "&#x1f9a1;"},
+ {"", ":swan:", "&#x1f9a2;"},
+ {"", ":peacock:", "&#x1f99a;"},
+ {"", ":parrot:", "&#x1f99c;"},
+ {"", ":sauropod:", "&#x1f995;"},
+ {"", ":t-rex:", "&#x1f996;"},
+ {"", ":cricket:", "&#x1f997;"},
+ {"", ":mosquito:", "&#x1f99f;"},
+ {"", ":microbe:", "&#x1f9a0;"},
+ {"", ":mango:", "&#x1f96d;"},
+ {"", ":coconut:", "&#x1f965;"},
+ {"", ":leafy green:", "&#x1f96c;"},
+ {"", ":broccoli:", "&#x1f966;"},
+ {"", ":pretzel:", "&#x1f968;"},
+ {"", ":bagel:", "&#x1f96f;"},
+ {"", ":cut of meat:", "&#x1f969;"},
+ {"", ":sandwich:", "&#x1f96a;"},
+ {"", ":bowl with spoon:", "&#x1f963;"},
+ {"", ":salt:", "&#x1f9c2;"},
+ {"", ":canned food:", "&#x1f96b;"},
+ {"", ":moon cake:", "&#x1f96e;"},
+ {"", ":dumpling:", "&#x1f95f;"},
+ {"", ":fortune cookie:", "&#x1f960;"},
+ {"", ":takeout box:", "&#x1f961;"},
+ {"", ":lobster:", "&#x1f99e;"},
+ {"", ":cupcake:", "&#x1f9c1;"},
+ {"", ":pie:", "&#x1f967;"},
+ {"", ":cup with straw:", "&#x1f964;"},
+ {"", ":chopsticks:", "&#x1f962;"},
+ {"", ":compass:", "&#x1f9ed;"},
+ {"", ":brick:", "&#x1f9f1;"},
+ {"", ":skateboard:", "&#x1f6f9;"},
+ {"", ":flying saucer:", "&#x1f6f8;"},
+ {"", ":luggage:", "&#x1f9f3;"},
+ {"", ":firecracker:", "&#x1f9e8;"},
+ {"", ":red envelope:", "&#x1f9e7;"},
+ {"", ":softball:", "&#x1f94e;"},
+ {"", ":flying disc:", "&#x1f94f;"},
+ {"", ":lacrosse:", "&#x1f94d;"},
+ {"", ":sled:", "&#x1f6f7;"},
+ {"", ":curling stone:", "&#x1f94c;"},
+ {"", ":nazar amulet:", "&#x1f9ff;"},
+ {"", ":jigsaw:", "&#x1f9e9;"},
+ {"", ":teddy bear:", "&#x1f9f8;"},
+ {"", ":chess pawn:", "&#x265f;"},
+ {"", ":thread:", "&#x1f9f5;"},
+ {"", ":yarn:", "&#x1f9f6;"},
+ {"", ":goggles:", "&#x1f97d;"},
+ {"", ":lab coat:", "&#x1f97c;"},
+ {"", ":scarf:", "&#x1f9e3;"},
+ {"", ":gloves:", "&#x1f9e4;"},
+ {"", ":coat:", "&#x1f9e5;"},
+ {"", ":socks:", "&#x1f9e6;"},
+ {"", ":hiking boot:", "&#x1f97e;"},
+ {"", ":flat shoe:", "&#x1f97f;"},
+ {"", ":billed cap:", "&#x1f9e2;"},
+ {"", ":abacus:", "&#x1f9ee;"},
+ {"", ":receipt:", "&#x1f9fe;"},
+ {"", ":toolbox:", "&#x1f9f0;"},
+ {"", ":magnet:", "&#x1f9f2;"},
+ {"", ":test tube:", "&#x1f9ea;"},
+ {"", ":petri dish:", "&#x1f9eb;"},
+ {"", ":dna:", "&#x1f9ec;"},
+ {"", ":lotion bottle:", "&#x1f9f4;"},
+ {"", ":safety pin:", "&#x1f9f7;"},
+ {"", ":broom:", "&#x1f9f9;"},
+ {"", ":basket:", "&#x1f9fa;"},
+ {"", ":roll of paper:", "&#x1f9fb;"},
+ {"", ":soap:", "&#x1f9fc;"},
+ {"", ":sponge:", "&#x1f9fd;"},
+ {"", ":fire extinguisher:", "&#x1f9ef;"},
+ {"", ":eject button:", "&#x23cf;"},
+ {"", ":medical symbol:", "&#x2695;"},
+ {"", ":infinity:", "&#x267e;"},
+ {"", ":pirate flag:", "&#x1f3f4;&#x200d;&#x2620;&#xfe0f;"},
+ {"", ":flag ascension island:", "&#x1f1e6;&#x1f1e8;"},
+ {"", ":flag bouvet island:", "&#x1f1e7;&#x1f1fb;"},
+ {"", ":flag clipperton island:", "&#x1f1e8;&#x1f1f5;"},
+ {"", ":flag diego garcia:", "&#x1f1e9;&#x1f1ec;"},
+ {"", ":flag ceuta & melilla:", "&#x1f1ea;&#x1f1e6;"},
+ {"", ":flag heard & mcdonald islands:", "&#x1f1ed;&#x1f1f2;"},
+ {"", ":flag st. martin:", "&#x1f1f2;&#x1f1eb;"},
+ {"", ":flag svalbard & jan mayen:", "&#x1f1f8;&#x1f1ef;"},
+ {"", ":flag tristan da cunha:", "&#x1f1f9;&#x1f1e6;"},
+ {"", ":flag u.s. outlying islands:", "&#x1f1fa;&#x1f1f2;"},
+ {"", ":flag united nations:", "&#x1f1fa;&#x1f1f3;"},
+ {"", ":flag england:", "&#x1f3f4;&#xe0067;&#xe0062;&#xe0065;&#xe006e;&#xe0067;&#xe007f;"},
+ {"", ":flag scotland:", "&#x1f3f4;&#xe0067;&#xe0062;&#xe0073;&#xe0063;&#xe0074;&#xe007f;"},
+ {"", ":flag wales:", "&#x1f3f4;&#xe0067;&#xe0062;&#xe0077;&#xe006c;&#xe0073;&#xe007f;"},
+ {"", ":waving hand light skin tone:", "&#x1f44b;&#x1f3fb;"},
+ {"", ":waving hand medium-light skin tone:", "&#x1f44b;&#x1f3fc;"},
+ {"", ":waving hand medium skin tone:", "&#x1f44b;&#x1f3fd;"},
+ {"", ":waving hand medium-dark skin tone:", "&#x1f44b;&#x1f3fe;"},
+ {"", ":waving hand dark skin tone:", "&#x1f44b;&#x1f3ff;"},
+ {"", ":raised back of hand light skin tone:", "&#x1f91a;&#x1f3fb;"},
+ {"", ":raised back of hand medium-light skin tone:", "&#x1f91a;&#x1f3fc;"},
+ {"", ":raised back of hand medium skin tone:", "&#x1f91a;&#x1f3fd;"},
+ {"", ":raised back of hand medium-dark skin tone:", "&#x1f91a;&#x1f3fe;"},
+ {"", ":raised back of hand dark skin tone:", "&#x1f91a;&#x1f3ff;"},
+ {"", ":hand with fingers splayed light skin tone:", "&#x1f590;&#x1f3fb;"},
+ {"", ":hand with fingers splayed medium-light skin tone:", "&#x1f590;&#x1f3fc;"},
+ {"", ":hand with fingers splayed medium skin tone:", "&#x1f590;&#x1f3fd;"},
+ {"", ":hand with fingers splayed medium-dark skin tone:", "&#x1f590;&#x1f3fe;"},
+ {"", ":hand with fingers splayed dark skin tone:", "&#x1f590;&#x1f3ff;"},
+ {"", ":raised hand light skin tone:", "&#x270b;&#x1f3fb;"},
+ {"", ":raised hand medium-light skin tone:", "&#x270b;&#x1f3fc;"},
+ {"", ":raised hand medium skin tone:", "&#x270b;&#x1f3fd;"},
+ {"", ":raised hand medium-dark skin tone:", "&#x270b;&#x1f3fe;"},
+ {"", ":raised hand dark skin tone:", "&#x270b;&#x1f3ff;"},
+ {"", ":vulcan salute light skin tone:", "&#x1f596;&#x1f3fb;"},
+ {"", ":vulcan salute medium-light skin tone:", "&#x1f596;&#x1f3fc;"},
+ {"", ":vulcan salute medium skin tone:", "&#x1f596;&#x1f3fd;"},
+ {"", ":vulcan salute medium-dark skin tone:", "&#x1f596;&#x1f3fe;"},
+ {"", ":vulcan salute dark skin tone:", "&#x1f596;&#x1f3ff;"},
+ {"", ":ok hand light skin tone:", "&#x1f44c;&#x1f3fb;"},
+ {"", ":ok hand medium-light skin tone:", "&#x1f44c;&#x1f3fc;"},
+ {"", ":ok hand medium skin tone:", "&#x1f44c;&#x1f3fd;"},
+ {"", ":ok hand medium-dark skin tone:", "&#x1f44c;&#x1f3fe;"},
+ {"", ":ok hand dark skin tone:", "&#x1f44c;&#x1f3ff;"},
+ {"", ":victory hand light skin tone:", "&#x270c;&#x1f3fb;"},
+ {"", ":victory hand medium-light skin tone:", "&#x270c;&#x1f3fc;"},
+ {"", ":victory hand medium skin tone:", "&#x270c;&#x1f3fd;"},
+ {"", ":victory hand medium-dark skin tone:", "&#x270c;&#x1f3fe;"},
+ {"", ":victory hand dark skin tone:", "&#x270c;&#x1f3ff;"},
+ {"", ":crossed fingers light skin tone:", "&#x1f91e;&#x1f3fb;"},
+ {"", ":crossed fingers medium-light skin tone:", "&#x1f91e;&#x1f3fc;"},
+ {"", ":crossed fingers medium skin tone:", "&#x1f91e;&#x1f3fd;"},
+ {"", ":crossed fingers medium-dark skin tone:", "&#x1f91e;&#x1f3fe;"},
+ {"", ":crossed fingers dark skin tone:", "&#x1f91e;&#x1f3ff;"},
+ {"", ":love-you gesture light skin tone:", "&#x1f91f;&#x1f3fb;"},
+ {"", ":love-you gesture medium-light skin tone:", "&#x1f91f;&#x1f3fc;"},
+ {"", ":love-you gesture medium skin tone:", "&#x1f91f;&#x1f3fd;"},
+ {"", ":love-you gesture medium-dark skin tone:", "&#x1f91f;&#x1f3fe;"},
+ {"", ":love-you gesture dark skin tone:", "&#x1f91f;&#x1f3ff;"},
+ {"", ":sign of the horns light skin tone:", "&#x1f918;&#x1f3fb;"},
+ {"", ":sign of the horns medium-light skin tone:", "&#x1f918;&#x1f3fc;"},
+ {"", ":sign of the horns medium skin tone:", "&#x1f918;&#x1f3fd;"},
+ {"", ":sign of the horns medium-dark skin tone:", "&#x1f918;&#x1f3fe;"},
+ {"", ":sign of the horns dark skin tone:", "&#x1f918;&#x1f3ff;"},
+ {"", ":call me hand light skin tone:", "&#x1f919;&#x1f3fb;"},
+ {"", ":call me hand medium-light skin tone:", "&#x1f919;&#x1f3fc;"},
+ {"", ":call me hand medium skin tone:", "&#x1f919;&#x1f3fd;"},
+ {"", ":call me hand medium-dark skin tone:", "&#x1f919;&#x1f3fe;"},
+ {"", ":call me hand dark skin tone:", "&#x1f919;&#x1f3ff;"},
+ {"", ":backhand index pointing left light skin tone:", "&#x1f448;&#x1f3fb;"},
+ {"", ":backhand index pointing left medium-light skin tone:", "&#x1f448;&#x1f3fc;"},
+ {"", ":backhand index pointing left medium skin tone:", "&#x1f448;&#x1f3fd;"},
+ {"", ":backhand index pointing left medium-dark skin tone:", "&#x1f448;&#x1f3fe;"},
+ {"", ":backhand index pointing left dark skin tone:", "&#x1f448;&#x1f3ff;"},
+ {"", ":backhand index pointing right light skin tone:", "&#x1f449;&#x1f3fb;"},
+ {"", ":backhand index pointing right medium-light skin tone:", "&#x1f449;&#x1f3fc;"},
+ {"", ":backhand index pointing right medium skin tone:", "&#x1f449;&#x1f3fd;"},
+ {"", ":backhand index pointing right medium-dark skin tone:", "&#x1f449;&#x1f3fe;"},
+ {"", ":backhand index pointing right dark skin tone:", "&#x1f449;&#x1f3ff;"},
+ {"", ":backhand index pointing up light skin tone:", "&#x1f446;&#x1f3fb;"},
+ {"", ":backhand index pointing up medium-light skin tone:", "&#x1f446;&#x1f3fc;"},
+ {"", ":backhand index pointing up medium skin tone:", "&#x1f446;&#x1f3fd;"},
+ {"", ":backhand index pointing up medium-dark skin tone:", "&#x1f446;&#x1f3fe;"},
+ {"", ":backhand index pointing up dark skin tone:", "&#x1f446;&#x1f3ff;"},
+ {"", ":middle finger light skin tone:", "&#x1f595;&#x1f3fb;"},
+ {"", ":middle finger medium-light skin tone:", "&#x1f595;&#x1f3fc;"},
+ {"", ":middle finger medium skin tone:", "&#x1f595;&#x1f3fd;"},
+ {"", ":middle finger medium-dark skin tone:", "&#x1f595;&#x1f3fe;"},
+ {"", ":middle finger dark skin tone:", "&#x1f595;&#x1f3ff;"},
+ {"", ":backhand index pointing down light skin tone:", "&#x1f447;&#x1f3fb;"},
+ {"", ":backhand index pointing down medium-light skin tone:", "&#x1f447;&#x1f3fc;"},
+ {"", ":backhand index pointing down medium skin tone:", "&#x1f447;&#x1f3fd;"},
+ {"", ":backhand index pointing down medium-dark skin tone:", "&#x1f447;&#x1f3fe;"},
+ {"", ":backhand index pointing down dark skin tone:", "&#x1f447;&#x1f3ff;"},
+ {"", ":index pointing up light skin tone:", "&#x261d;&#x1f3fb;"},
+ {"", ":index pointing up medium-light skin tone:", "&#x261d;&#x1f3fc;"},
+ {"", ":index pointing up medium skin tone:", "&#x261d;&#x1f3fd;"},
+ {"", ":index pointing up medium-dark skin tone:", "&#x261d;&#x1f3fe;"},
+ {"", ":index pointing up dark skin tone:", "&#x261d;&#x1f3ff;"},
+ {"", ":thumbs up light skin tone:", "&#x1f44d;&#x1f3fb;"},
+ {"", ":thumbs up medium-light skin tone:", "&#x1f44d;&#x1f3fc;"},
+ {"", ":thumbs up medium skin tone:", "&#x1f44d;&#x1f3fd;"},
+ {"", ":thumbs up medium-dark skin tone:", "&#x1f44d;&#x1f3fe;"},
+ {"", ":thumbs up dark skin tone:", "&#x1f44d;&#x1f3ff;"},
+ {"", ":thumbs down light skin tone:", "&#x1f44e;&#x1f3fb;"},
+ {"", ":thumbs down medium-light skin tone:", "&#x1f44e;&#x1f3fc;"},
+ {"", ":thumbs down medium skin tone:", "&#x1f44e;&#x1f3fd;"},
+ {"", ":thumbs down medium-dark skin tone:", "&#x1f44e;&#x1f3fe;"},
+ {"", ":thumbs down dark skin tone:", "&#x1f44e;&#x1f3ff;"},
+ {"", ":raised fist light skin tone:", "&#x270a;&#x1f3fb;"},
+ {"", ":raised fist medium-light skin tone:", "&#x270a;&#x1f3fc;"},
+ {"", ":raised fist medium skin tone:", "&#x270a;&#x1f3fd;"},
+ {"", ":raised fist medium-dark skin tone:", "&#x270a;&#x1f3fe;"},
+ {"", ":raised fist dark skin tone:", "&#x270a;&#x1f3ff;"},
+ {"", ":oncoming fist light skin tone:", "&#x1f44a;&#x1f3fb;"},
+ {"", ":oncoming fist medium-light skin tone:", "&#x1f44a;&#x1f3fc;"},
+ {"", ":oncoming fist medium skin tone:", "&#x1f44a;&#x1f3fd;"},
+ {"", ":oncoming fist medium-dark skin tone:", "&#x1f44a;&#x1f3fe;"},
+ {"", ":oncoming fist dark skin tone:", "&#x1f44a;&#x1f3ff;"},
+ {"", ":left-facing fist light skin tone:", "&#x1f91b;&#x1f3fb;"},
+ {"", ":left-facing fist medium-light skin tone:", "&#x1f91b;&#x1f3fc;"},
+ {"", ":left-facing fist medium skin tone:", "&#x1f91b;&#x1f3fd;"},
+ {"", ":left-facing fist medium-dark skin tone:", "&#x1f91b;&#x1f3fe;"},
+ {"", ":left-facing fist dark skin tone:", "&#x1f91b;&#x1f3ff;"},
+ {"", ":right-facing fist light skin tone:", "&#x1f91c;&#x1f3fb;"},
+ {"", ":right-facing fist medium-light skin tone:", "&#x1f91c;&#x1f3fc;"},
+ {"", ":right-facing fist medium skin tone:", "&#x1f91c;&#x1f3fd;"},
+ {"", ":right-facing fist medium-dark skin tone:", "&#x1f91c;&#x1f3fe;"},
+ {"", ":right-facing fist dark skin tone:", "&#x1f91c;&#x1f3ff;"},
+ {"", ":clapping hands light skin tone:", "&#x1f44f;&#x1f3fb;"},
+ {"", ":clapping hands medium-light skin tone:", "&#x1f44f;&#x1f3fc;"},
+ {"", ":clapping hands medium skin tone:", "&#x1f44f;&#x1f3fd;"},
+ {"", ":clapping hands medium-dark skin tone:", "&#x1f44f;&#x1f3fe;"},
+ {"", ":clapping hands dark skin tone:", "&#x1f44f;&#x1f3ff;"},
+ {"", ":raising hands light skin tone:", "&#x1f64c;&#x1f3fb;"},
+ {"", ":raising hands medium-light skin tone:", "&#x1f64c;&#x1f3fc;"},
+ {"", ":raising hands medium skin tone:", "&#x1f64c;&#x1f3fd;"},
+ {"", ":raising hands medium-dark skin tone:", "&#x1f64c;&#x1f3fe;"},
+ {"", ":raising hands dark skin tone:", "&#x1f64c;&#x1f3ff;"},
+ {"", ":open hands light skin tone:", "&#x1f450;&#x1f3fb;"},
+ {"", ":open hands medium-light skin tone:", "&#x1f450;&#x1f3fc;"},
+ {"", ":open hands medium skin tone:", "&#x1f450;&#x1f3fd;"},
+ {"", ":open hands medium-dark skin tone:", "&#x1f450;&#x1f3fe;"},
+ {"", ":open hands dark skin tone:", "&#x1f450;&#x1f3ff;"},
+ {"", ":palms up together light skin tone:", "&#x1f932;&#x1f3fb;"},
+ {"", ":palms up together medium-light skin tone:", "&#x1f932;&#x1f3fc;"},
+ {"", ":palms up together medium skin tone:", "&#x1f932;&#x1f3fd;"},
+ {"", ":palms up together medium-dark skin tone:", "&#x1f932;&#x1f3fe;"},
+ {"", ":palms up together dark skin tone:", "&#x1f932;&#x1f3ff;"},
+ {"", ":folded hands light skin tone:", "&#x1f64f;&#x1f3fb;"},
+ {"", ":folded hands medium-light skin tone:", "&#x1f64f;&#x1f3fc;"},
+ {"", ":folded hands medium skin tone:", "&#x1f64f;&#x1f3fd;"},
+ {"", ":folded hands medium-dark skin tone:", "&#x1f64f;&#x1f3fe;"},
+ {"", ":folded hands dark skin tone:", "&#x1f64f;&#x1f3ff;"},
+ {"", ":writing hand light skin tone:", "&#x270d;&#x1f3fb;"},
+ {"", ":writing hand medium-light skin tone:", "&#x270d;&#x1f3fc;"},
+ {"", ":writing hand medium skin tone:", "&#x270d;&#x1f3fd;"},
+ {"", ":writing hand medium-dark skin tone:", "&#x270d;&#x1f3fe;"},
+ {"", ":writing hand dark skin tone:", "&#x270d;&#x1f3ff;"},
+ {"", ":nail polish light skin tone:", "&#x1f485;&#x1f3fb;"},
+ {"", ":nail polish medium-light skin tone:", "&#x1f485;&#x1f3fc;"},
+ {"", ":nail polish medium skin tone:", "&#x1f485;&#x1f3fd;"},
+ {"", ":nail polish medium-dark skin tone:", "&#x1f485;&#x1f3fe;"},
+ {"", ":nail polish dark skin tone:", "&#x1f485;&#x1f3ff;"},
+ {"", ":selfie light skin tone:", "&#x1f933;&#x1f3fb;"},
+ {"", ":selfie medium-light skin tone:", "&#x1f933;&#x1f3fc;"},
+ {"", ":selfie medium skin tone:", "&#x1f933;&#x1f3fd;"},
+ {"", ":selfie medium-dark skin tone:", "&#x1f933;&#x1f3fe;"},
+ {"", ":selfie dark skin tone:", "&#x1f933;&#x1f3ff;"},
+ {"", ":flexed biceps light skin tone:", "&#x1f4aa;&#x1f3fb;"},
+ {"", ":flexed biceps medium-light skin tone:", "&#x1f4aa;&#x1f3fc;"},
+ {"", ":flexed biceps medium skin tone:", "&#x1f4aa;&#x1f3fd;"},
+ {"", ":flexed biceps medium-dark skin tone:", "&#x1f4aa;&#x1f3fe;"},
+ {"", ":flexed biceps dark skin tone:", "&#x1f4aa;&#x1f3ff;"},
+ {"", ":leg light skin tone:", "&#x1f9b5;&#x1f3fb;"},
+ {"", ":leg medium-light skin tone:", "&#x1f9b5;&#x1f3fc;"},
+ {"", ":leg medium skin tone:", "&#x1f9b5;&#x1f3fd;"},
+ {"", ":leg medium-dark skin tone:", "&#x1f9b5;&#x1f3fe;"},
+ {"", ":leg dark skin tone:", "&#x1f9b5;&#x1f3ff;"},
+ {"", ":foot light skin tone:", "&#x1f9b6;&#x1f3fb;"},
+ {"", ":foot medium-light skin tone:", "&#x1f9b6;&#x1f3fc;"},
+ {"", ":foot medium skin tone:", "&#x1f9b6;&#x1f3fd;"},
+ {"", ":foot medium-dark skin tone:", "&#x1f9b6;&#x1f3fe;"},
+ {"", ":foot dark skin tone:", "&#x1f9b6;&#x1f3ff;"},
+ {"", ":ear light skin tone:", "&#x1f442;&#x1f3fb;"},
+ {"", ":ear medium-light skin tone:", "&#x1f442;&#x1f3fc;"},
+ {"", ":ear medium skin tone:", "&#x1f442;&#x1f3fd;"},
+ {"", ":ear medium-dark skin tone:", "&#x1f442;&#x1f3fe;"},
+ {"", ":ear dark skin tone:", "&#x1f442;&#x1f3ff;"},
+ {"", ":nose light skin tone:", "&#x1f443;&#x1f3fb;"},
+ {"", ":nose medium-light skin tone:", "&#x1f443;&#x1f3fc;"},
+ {"", ":nose medium skin tone:", "&#x1f443;&#x1f3fd;"},
+ {"", ":nose medium-dark skin tone:", "&#x1f443;&#x1f3fe;"},
+ {"", ":nose dark skin tone:", "&#x1f443;&#x1f3ff;"},
+ {"", ":baby light skin tone:", "&#x1f476;&#x1f3fb;"},
+ {"", ":baby medium-light skin tone:", "&#x1f476;&#x1f3fc;"},
+ {"", ":baby medium skin tone:", "&#x1f476;&#x1f3fd;"},
+ {"", ":baby medium-dark skin tone:", "&#x1f476;&#x1f3fe;"},
+ {"", ":baby dark skin tone:", "&#x1f476;&#x1f3ff;"},
+ {"", ":child light skin tone:", "&#x1f9d2;&#x1f3fb;"},
+ {"", ":child medium-light skin tone:", "&#x1f9d2;&#x1f3fc;"},
+ {"", ":child medium skin tone:", "&#x1f9d2;&#x1f3fd;"},
+ {"", ":child medium-dark skin tone:", "&#x1f9d2;&#x1f3fe;"},
+ {"", ":child dark skin tone:", "&#x1f9d2;&#x1f3ff;"},
+ {"", ":boy light skin tone:", "&#x1f466;&#x1f3fb;"},
+ {"", ":boy medium-light skin tone:", "&#x1f466;&#x1f3fc;"},
+ {"", ":boy medium skin tone:", "&#x1f466;&#x1f3fd;"},
+ {"", ":boy medium-dark skin tone:", "&#x1f466;&#x1f3fe;"},
+ {"", ":boy dark skin tone:", "&#x1f466;&#x1f3ff;"},
+ {"", ":girl light skin tone:", "&#x1f467;&#x1f3fb;"},
+ {"", ":girl medium-light skin tone:", "&#x1f467;&#x1f3fc;"},
+ {"", ":girl medium skin tone:", "&#x1f467;&#x1f3fd;"},
+ {"", ":girl medium-dark skin tone:", "&#x1f467;&#x1f3fe;"},
+ {"", ":girl dark skin tone:", "&#x1f467;&#x1f3ff;"},
+ {"", ":person light skin tone:", "&#x1f9d1;&#x1f3fb;"},
+ {"", ":person medium-light skin tone:", "&#x1f9d1;&#x1f3fc;"},
+ {"", ":person medium skin tone:", "&#x1f9d1;&#x1f3fd;"},
+ {"", ":person medium-dark skin tone:", "&#x1f9d1;&#x1f3fe;"},
+ {"", ":person dark skin tone:", "&#x1f9d1;&#x1f3ff;"},
+ {"", ":person light skin tone, blond hair:", "&#x1f471;&#x1f3fb;"},
+ {"", ":person medium-light skin tone, blond hair:", "&#x1f471;&#x1f3fc;"},
+ {"", ":person medium skin tone, blond hair:", "&#x1f471;&#x1f3fd;"},
+ {"", ":person medium-dark skin tone, blond hair:", "&#x1f471;&#x1f3fe;"},
+ {"", ":person dark skin tone, blond hair:", "&#x1f471;&#x1f3ff;"},
+ {"", ":man light skin tone:", "&#x1f468;&#x1f3fb;"},
+ {"", ":man medium-light skin tone:", "&#x1f468;&#x1f3fc;"},
+ {"", ":man medium skin tone:", "&#x1f468;&#x1f3fd;"},
+ {"", ":man medium-dark skin tone:", "&#x1f468;&#x1f3fe;"},
+ {"", ":man dark skin tone:", "&#x1f468;&#x1f3ff;"},
+ {"", ":man light skin tone, blond hair:", "&#x1f471;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man medium-light skin tone, blond hair:", "&#x1f471;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man medium skin tone, blond hair:", "&#x1f471;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man medium-dark skin tone, blond hair:", "&#x1f471;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man dark skin tone, blond hair:", "&#x1f471;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man light skin tone, red hair:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f9b0;"},
+ {"", ":man medium-light skin tone, red hair:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f9b0;"},
+ {"", ":man medium skin tone, red hair:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f9b0;"},
+ {"", ":man medium-dark skin tone, red hair:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f9b0;"},
+ {"", ":man dark skin tone, red hair:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f9b0;"},
+ {"", ":man light skin tone, curly hair:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f9b1;"},
+ {"", ":man medium-light skin tone, curly hair:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f9b1;"},
+ {"", ":man medium skin tone, curly hair:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f9b1;"},
+ {"", ":man medium-dark skin tone, curly hair:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f9b1;"},
+ {"", ":man dark skin tone, curly hair:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f9b1;"},
+ {"", ":man light skin tone, white hair:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f9b3;"},
+ {"", ":man medium-light skin tone, white hair:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f9b3;"},
+ {"", ":man medium skin tone, white hair:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f9b3;"},
+ {"", ":man medium-dark skin tone, white hair:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f9b3;"},
+ {"", ":man dark skin tone, white hair:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f9b3;"},
+ {"", ":man light skin tone, bald:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f9b2;"},
+ {"", ":man medium-light skin tone, bald:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f9b2;"},
+ {"", ":man medium skin tone, bald:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f9b2;"},
+ {"", ":man medium-dark skin tone, bald:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f9b2;"},
+ {"", ":man dark skin tone, bald:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f9b2;"},
+ {"", ":man light skin tone, beard:", "&#x1f9d4;&#x1f3fb;"},
+ {"", ":man medium-light skin tone, beard:", "&#x1f9d4;&#x1f3fc;"},
+ {"", ":man medium skin tone, beard:", "&#x1f9d4;&#x1f3fd;"},
+ {"", ":man medium-dark skin tone, beard:", "&#x1f9d4;&#x1f3fe;"},
+ {"", ":man dark skin tone, beard:", "&#x1f9d4;&#x1f3ff;"},
+ {"", ":woman light skin tone:", "&#x1f469;&#x1f3fb;"},
+ {"", ":woman medium-light skin tone:", "&#x1f469;&#x1f3fc;"},
+ {"", ":woman medium skin tone:", "&#x1f469;&#x1f3fd;"},
+ {"", ":woman medium-dark skin tone:", "&#x1f469;&#x1f3fe;"},
+ {"", ":woman dark skin tone:", "&#x1f469;&#x1f3ff;"},
+ {"", ":woman light skin tone, blond hair:", "&#x1f471;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman medium-light skin tone, blond hair:", "&#x1f471;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman medium skin tone, blond hair:", "&#x1f471;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman medium-dark skin tone, blond hair:", "&#x1f471;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman dark skin tone, blond hair:", "&#x1f471;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman light skin tone, red hair:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f9b0;"},
+ {"", ":woman medium-light skin tone, red hair:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f9b0;"},
+ {"", ":woman medium skin tone, red hair:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f9b0;"},
+ {"", ":woman medium-dark skin tone, red hair:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f9b0;"},
+ {"", ":woman dark skin tone, red hair:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f9b0;"},
+ {"", ":woman light skin tone, curly hair:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f9b1;"},
+ {"", ":woman medium-light skin tone, curly hair:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f9b1;"},
+ {"", ":woman medium skin tone, curly hair:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f9b1;"},
+ {"", ":woman medium-dark skin tone, curly hair:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f9b1;"},
+ {"", ":woman dark skin tone, curly hair:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f9b1;"},
+ {"", ":woman light skin tone, white hair:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f9b3;"},
+ {"", ":woman medium-light skin tone, white hair:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f9b3;"},
+ {"", ":woman medium skin tone, white hair:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f9b3;"},
+ {"", ":woman medium-dark skin tone, white hair:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f9b3;"},
+ {"", ":woman dark skin tone, white hair:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f9b3;"},
+ {"", ":woman light skin tone, bald:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f9b2;"},
+ {"", ":woman medium-light skin tone, bald:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f9b2;"},
+ {"", ":woman medium skin tone, bald:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f9b2;"},
+ {"", ":woman medium-dark skin tone, bald:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f9b2;"},
+ {"", ":woman dark skin tone, bald:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f9b2;"},
+ {"", ":older person light skin tone:", "&#x1f9d3;&#x1f3fb;"},
+ {"", ":older person medium-light skin tone:", "&#x1f9d3;&#x1f3fc;"},
+ {"", ":older person medium skin tone:", "&#x1f9d3;&#x1f3fd;"},
+ {"", ":older person medium-dark skin tone:", "&#x1f9d3;&#x1f3fe;"},
+ {"", ":older person dark skin tone:", "&#x1f9d3;&#x1f3ff;"},
+ {"", ":old man light skin tone:", "&#x1f474;&#x1f3fb;"},
+ {"", ":old man medium-light skin tone:", "&#x1f474;&#x1f3fc;"},
+ {"", ":old man medium skin tone:", "&#x1f474;&#x1f3fd;"},
+ {"", ":old man medium-dark skin tone:", "&#x1f474;&#x1f3fe;"},
+ {"", ":old man dark skin tone:", "&#x1f474;&#x1f3ff;"},
+ {"", ":old woman light skin tone:", "&#x1f475;&#x1f3fb;"},
+ {"", ":old woman medium-light skin tone:", "&#x1f475;&#x1f3fc;"},
+ {"", ":old woman medium skin tone:", "&#x1f475;&#x1f3fd;"},
+ {"", ":old woman medium-dark skin tone:", "&#x1f475;&#x1f3fe;"},
+ {"", ":old woman dark skin tone:", "&#x1f475;&#x1f3ff;"},
+ {"", ":person frowning light skin tone:", "&#x1f64d;&#x1f3fb;"},
+ {"", ":person frowning medium-light skin tone:", "&#x1f64d;&#x1f3fc;"},
+ {"", ":person frowning medium skin tone:", "&#x1f64d;&#x1f3fd;"},
+ {"", ":person frowning medium-dark skin tone:", "&#x1f64d;&#x1f3fe;"},
+ {"", ":person frowning dark skin tone:", "&#x1f64d;&#x1f3ff;"},
+ {"", ":man frowning light skin tone:", "&#x1f64d;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man frowning medium-light skin tone:", "&#x1f64d;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man frowning medium skin tone:", "&#x1f64d;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man frowning medium-dark skin tone:", "&#x1f64d;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man frowning dark skin tone:", "&#x1f64d;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman frowning light skin tone:", "&#x1f64d;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman frowning medium-light skin tone:", "&#x1f64d;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman frowning medium skin tone:", "&#x1f64d;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman frowning medium-dark skin tone:", "&#x1f64d;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman frowning dark skin tone:", "&#x1f64d;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person pouting light skin tone:", "&#x1f64e;&#x1f3fb;"},
+ {"", ":person pouting medium-light skin tone:", "&#x1f64e;&#x1f3fc;"},
+ {"", ":person pouting medium skin tone:", "&#x1f64e;&#x1f3fd;"},
+ {"", ":person pouting medium-dark skin tone:", "&#x1f64e;&#x1f3fe;"},
+ {"", ":person pouting dark skin tone:", "&#x1f64e;&#x1f3ff;"},
+ {"", ":man pouting light skin tone:", "&#x1f64e;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man pouting medium-light skin tone:", "&#x1f64e;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man pouting medium skin tone:", "&#x1f64e;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man pouting medium-dark skin tone:", "&#x1f64e;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man pouting dark skin tone:", "&#x1f64e;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman pouting light skin tone:", "&#x1f64e;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman pouting medium-light skin tone:", "&#x1f64e;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman pouting medium skin tone:", "&#x1f64e;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman pouting medium-dark skin tone:", "&#x1f64e;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman pouting dark skin tone:", "&#x1f64e;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person gesturing no light skin tone:", "&#x1f645;&#x1f3fb;"},
+ {"", ":person gesturing no medium-light skin tone:", "&#x1f645;&#x1f3fc;"},
+ {"", ":person gesturing no medium skin tone:", "&#x1f645;&#x1f3fd;"},
+ {"", ":person gesturing no medium-dark skin tone:", "&#x1f645;&#x1f3fe;"},
+ {"", ":person gesturing no dark skin tone:", "&#x1f645;&#x1f3ff;"},
+ {"", ":man gesturing no light skin tone:", "&#x1f645;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man gesturing no medium-light skin tone:", "&#x1f645;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man gesturing no medium skin tone:", "&#x1f645;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man gesturing no medium-dark skin tone:", "&#x1f645;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man gesturing no dark skin tone:", "&#x1f645;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman gesturing no light skin tone:", "&#x1f645;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman gesturing no medium-light skin tone:", "&#x1f645;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman gesturing no medium skin tone:", "&#x1f645;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman gesturing no medium-dark skin tone:", "&#x1f645;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman gesturing no dark skin tone:", "&#x1f645;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person gesturing ok light skin tone:", "&#x1f646;&#x1f3fb;"},
+ {"", ":person gesturing ok medium-light skin tone:", "&#x1f646;&#x1f3fc;"},
+ {"", ":person gesturing ok medium skin tone:", "&#x1f646;&#x1f3fd;"},
+ {"", ":person gesturing ok medium-dark skin tone:", "&#x1f646;&#x1f3fe;"},
+ {"", ":person gesturing ok dark skin tone:", "&#x1f646;&#x1f3ff;"},
+ {"", ":man gesturing ok light skin tone:", "&#x1f646;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man gesturing ok medium-light skin tone:", "&#x1f646;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man gesturing ok medium skin tone:", "&#x1f646;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man gesturing ok medium-dark skin tone:", "&#x1f646;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man gesturing ok dark skin tone:", "&#x1f646;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman gesturing ok light skin tone:", "&#x1f646;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman gesturing ok medium-light skin tone:", "&#x1f646;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman gesturing ok medium skin tone:", "&#x1f646;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman gesturing ok medium-dark skin tone:", "&#x1f646;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman gesturing ok dark skin tone:", "&#x1f646;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person tipping hand light skin tone:", "&#x1f481;&#x1f3fb;"},
+ {"", ":person tipping hand medium-light skin tone:", "&#x1f481;&#x1f3fc;"},
+ {"", ":person tipping hand medium skin tone:", "&#x1f481;&#x1f3fd;"},
+ {"", ":person tipping hand medium-dark skin tone:", "&#x1f481;&#x1f3fe;"},
+ {"", ":person tipping hand dark skin tone:", "&#x1f481;&#x1f3ff;"},
+ {"", ":man tipping hand light skin tone:", "&#x1f481;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man tipping hand medium-light skin tone:", "&#x1f481;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man tipping hand medium skin tone:", "&#x1f481;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man tipping hand medium-dark skin tone:", "&#x1f481;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man tipping hand dark skin tone:", "&#x1f481;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman tipping hand light skin tone:", "&#x1f481;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman tipping hand medium-light skin tone:", "&#x1f481;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman tipping hand medium skin tone:", "&#x1f481;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman tipping hand medium-dark skin tone:", "&#x1f481;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman tipping hand dark skin tone:", "&#x1f481;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person raising hand light skin tone:", "&#x1f64b;&#x1f3fb;"},
+ {"", ":person raising hand medium-light skin tone:", "&#x1f64b;&#x1f3fc;"},
+ {"", ":person raising hand medium skin tone:", "&#x1f64b;&#x1f3fd;"},
+ {"", ":person raising hand medium-dark skin tone:", "&#x1f64b;&#x1f3fe;"},
+ {"", ":person raising hand dark skin tone:", "&#x1f64b;&#x1f3ff;"},
+ {"", ":man raising hand light skin tone:", "&#x1f64b;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man raising hand medium-light skin tone:", "&#x1f64b;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man raising hand medium skin tone:", "&#x1f64b;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man raising hand medium-dark skin tone:", "&#x1f64b;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man raising hand dark skin tone:", "&#x1f64b;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman raising hand light skin tone:", "&#x1f64b;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman raising hand medium-light skin tone:", "&#x1f64b;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman raising hand medium skin tone:", "&#x1f64b;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman raising hand medium-dark skin tone:", "&#x1f64b;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman raising hand dark skin tone:", "&#x1f64b;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person bowing light skin tone:", "&#x1f647;&#x1f3fb;"},
+ {"", ":person bowing medium-light skin tone:", "&#x1f647;&#x1f3fc;"},
+ {"", ":person bowing medium skin tone:", "&#x1f647;&#x1f3fd;"},
+ {"", ":person bowing medium-dark skin tone:", "&#x1f647;&#x1f3fe;"},
+ {"", ":person bowing dark skin tone:", "&#x1f647;&#x1f3ff;"},
+ {"", ":man bowing light skin tone:", "&#x1f647;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man bowing medium-light skin tone:", "&#x1f647;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man bowing medium skin tone:", "&#x1f647;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man bowing medium-dark skin tone:", "&#x1f647;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man bowing dark skin tone:", "&#x1f647;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman bowing light skin tone:", "&#x1f647;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman bowing medium-light skin tone:", "&#x1f647;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman bowing medium skin tone:", "&#x1f647;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman bowing medium-dark skin tone:", "&#x1f647;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman bowing dark skin tone:", "&#x1f647;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person facepalming light skin tone:", "&#x1f926;&#x1f3fb;"},
+ {"", ":person facepalming medium-light skin tone:", "&#x1f926;&#x1f3fc;"},
+ {"", ":person facepalming medium skin tone:", "&#x1f926;&#x1f3fd;"},
+ {"", ":person facepalming medium-dark skin tone:", "&#x1f926;&#x1f3fe;"},
+ {"", ":person facepalming dark skin tone:", "&#x1f926;&#x1f3ff;"},
+ {"", ":man facepalming light skin tone:", "&#x1f926;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man facepalming medium-light skin tone:", "&#x1f926;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man facepalming medium skin tone:", "&#x1f926;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man facepalming medium-dark skin tone:", "&#x1f926;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man facepalming dark skin tone:", "&#x1f926;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman facepalming light skin tone:", "&#x1f926;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman facepalming medium-light skin tone:", "&#x1f926;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman facepalming medium skin tone:", "&#x1f926;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman facepalming medium-dark skin tone:", "&#x1f926;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman facepalming dark skin tone:", "&#x1f926;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person shrugging light skin tone:", "&#x1f937;&#x1f3fb;"},
+ {"", ":person shrugging medium-light skin tone:", "&#x1f937;&#x1f3fc;"},
+ {"", ":person shrugging medium skin tone:", "&#x1f937;&#x1f3fd;"},
+ {"", ":person shrugging medium-dark skin tone:", "&#x1f937;&#x1f3fe;"},
+ {"", ":person shrugging dark skin tone:", "&#x1f937;&#x1f3ff;"},
+ {"", ":man shrugging light skin tone:", "&#x1f937;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man shrugging medium-light skin tone:", "&#x1f937;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man shrugging medium skin tone:", "&#x1f937;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man shrugging medium-dark skin tone:", "&#x1f937;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man shrugging dark skin tone:", "&#x1f937;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman shrugging light skin tone:", "&#x1f937;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman shrugging medium-light skin tone:", "&#x1f937;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman shrugging medium skin tone:", "&#x1f937;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman shrugging medium-dark skin tone:", "&#x1f937;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman shrugging dark skin tone:", "&#x1f937;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":man health worker light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x2695;&#xfe0f;"},
+ {"", ":man health worker medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x2695;&#xfe0f;"},
+ {"", ":man health worker medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x2695;&#xfe0f;"},
+ {"", ":man health worker medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x2695;&#xfe0f;"},
+ {"", ":man health worker dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x2695;&#xfe0f;"},
+ {"", ":woman health worker light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x2695;&#xfe0f;"},
+ {"", ":woman health worker medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x2695;&#xfe0f;"},
+ {"", ":woman health worker medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x2695;&#xfe0f;"},
+ {"", ":woman health worker medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x2695;&#xfe0f;"},
+ {"", ":woman health worker dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x2695;&#xfe0f;"},
+ {"", ":man student light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f393;"},
+ {"", ":man student medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f393;"},
+ {"", ":man student medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f393;"},
+ {"", ":man student medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f393;"},
+ {"", ":man student dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f393;"},
+ {"", ":woman student light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f393;"},
+ {"", ":woman student medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f393;"},
+ {"", ":woman student medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f393;"},
+ {"", ":woman student medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f393;"},
+ {"", ":woman student dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f393;"},
+ {"", ":man teacher light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f3eb;"},
+ {"", ":man teacher medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f3eb;"},
+ {"", ":man teacher medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f3eb;"},
+ {"", ":man teacher medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f3eb;"},
+ {"", ":man teacher dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f3eb;"},
+ {"", ":woman teacher light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f3eb;"},
+ {"", ":woman teacher medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f3eb;"},
+ {"", ":woman teacher medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f3eb;"},
+ {"", ":woman teacher medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f3eb;"},
+ {"", ":woman teacher dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f3eb;"},
+ {"", ":man judge light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x2696;&#xfe0f;"},
+ {"", ":man judge medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x2696;&#xfe0f;"},
+ {"", ":man judge medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x2696;&#xfe0f;"},
+ {"", ":man judge medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x2696;&#xfe0f;"},
+ {"", ":man judge dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x2696;&#xfe0f;"},
+ {"", ":woman judge light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x2696;&#xfe0f;"},
+ {"", ":woman judge medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x2696;&#xfe0f;"},
+ {"", ":woman judge medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x2696;&#xfe0f;"},
+ {"", ":woman judge medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x2696;&#xfe0f;"},
+ {"", ":woman judge dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x2696;&#xfe0f;"},
+ {"", ":man farmer light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f33e;"},
+ {"", ":man farmer medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f33e;"},
+ {"", ":man farmer medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f33e;"},
+ {"", ":man farmer medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f33e;"},
+ {"", ":man farmer dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f33e;"},
+ {"", ":woman farmer light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f33e;"},
+ {"", ":woman farmer medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f33e;"},
+ {"", ":woman farmer medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f33e;"},
+ {"", ":woman farmer medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f33e;"},
+ {"", ":woman farmer dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f33e;"},
+ {"", ":man cook light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f373;"},
+ {"", ":man cook medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f373;"},
+ {"", ":man cook medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f373;"},
+ {"", ":man cook medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f373;"},
+ {"", ":man cook dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f373;"},
+ {"", ":woman cook light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f373;"},
+ {"", ":woman cook medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f373;"},
+ {"", ":woman cook medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f373;"},
+ {"", ":woman cook medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f373;"},
+ {"", ":woman cook dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f373;"},
+ {"", ":man mechanic light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f527;"},
+ {"", ":man mechanic medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f527;"},
+ {"", ":man mechanic medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f527;"},
+ {"", ":man mechanic medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f527;"},
+ {"", ":man mechanic dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f527;"},
+ {"", ":woman mechanic light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f527;"},
+ {"", ":woman mechanic medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f527;"},
+ {"", ":woman mechanic medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f527;"},
+ {"", ":woman mechanic medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f527;"},
+ {"", ":woman mechanic dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f527;"},
+ {"", ":man factory worker light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f3ed;"},
+ {"", ":man factory worker medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f3ed;"},
+ {"", ":man factory worker medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f3ed;"},
+ {"", ":man factory worker medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f3ed;"},
+ {"", ":man factory worker dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f3ed;"},
+ {"", ":woman factory worker light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f3ed;"},
+ {"", ":woman factory worker medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f3ed;"},
+ {"", ":woman factory worker medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f3ed;"},
+ {"", ":woman factory worker medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f3ed;"},
+ {"", ":woman factory worker dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f3ed;"},
+ {"", ":man office worker light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f4bc;"},
+ {"", ":man office worker medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f4bc;"},
+ {"", ":man office worker medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f4bc;"},
+ {"", ":man office worker medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f4bc;"},
+ {"", ":man office worker dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f4bc;"},
+ {"", ":woman office worker light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f4bc;"},
+ {"", ":woman office worker medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f4bc;"},
+ {"", ":woman office worker medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f4bc;"},
+ {"", ":woman office worker medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f4bc;"},
+ {"", ":woman office worker dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f4bc;"},
+ {"", ":man scientist light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f52c;"},
+ {"", ":man scientist medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f52c;"},
+ {"", ":man scientist medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f52c;"},
+ {"", ":man scientist medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f52c;"},
+ {"", ":man scientist dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f52c;"},
+ {"", ":woman scientist light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f52c;"},
+ {"", ":woman scientist medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f52c;"},
+ {"", ":woman scientist medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f52c;"},
+ {"", ":woman scientist medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f52c;"},
+ {"", ":woman scientist dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f52c;"},
+ {"", ":man technologist light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f4bb;"},
+ {"", ":man technologist medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f4bb;"},
+ {"", ":man technologist medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f4bb;"},
+ {"", ":man technologist medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f4bb;"},
+ {"", ":man technologist dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f4bb;"},
+ {"", ":woman technologist light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f4bb;"},
+ {"", ":woman technologist medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f4bb;"},
+ {"", ":woman technologist medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f4bb;"},
+ {"", ":woman technologist medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f4bb;"},
+ {"", ":woman technologist dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f4bb;"},
+ {"", ":man singer light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f3a4;"},
+ {"", ":man singer medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f3a4;"},
+ {"", ":man singer medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f3a4;"},
+ {"", ":man singer medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f3a4;"},
+ {"", ":man singer dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f3a4;"},
+ {"", ":woman singer light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f3a4;"},
+ {"", ":woman singer medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f3a4;"},
+ {"", ":woman singer medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f3a4;"},
+ {"", ":woman singer medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f3a4;"},
+ {"", ":woman singer dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f3a4;"},
+ {"", ":man artist light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f3a8;"},
+ {"", ":man artist medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f3a8;"},
+ {"", ":man artist medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f3a8;"},
+ {"", ":man artist medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f3a8;"},
+ {"", ":man artist dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f3a8;"},
+ {"", ":woman artist light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f3a8;"},
+ {"", ":woman artist medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f3a8;"},
+ {"", ":woman artist medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f3a8;"},
+ {"", ":woman artist medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f3a8;"},
+ {"", ":woman artist dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f3a8;"},
+ {"", ":man pilot light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x2708;&#xfe0f;"},
+ {"", ":man pilot medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x2708;&#xfe0f;"},
+ {"", ":man pilot medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x2708;&#xfe0f;"},
+ {"", ":man pilot medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x2708;&#xfe0f;"},
+ {"", ":man pilot dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x2708;&#xfe0f;"},
+ {"", ":woman pilot light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x2708;&#xfe0f;"},
+ {"", ":woman pilot medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x2708;&#xfe0f;"},
+ {"", ":woman pilot medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x2708;&#xfe0f;"},
+ {"", ":woman pilot medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x2708;&#xfe0f;"},
+ {"", ":woman pilot dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x2708;&#xfe0f;"},
+ {"", ":man astronaut light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f680;"},
+ {"", ":man astronaut medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f680;"},
+ {"", ":man astronaut medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f680;"},
+ {"", ":man astronaut medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f680;"},
+ {"", ":man astronaut dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f680;"},
+ {"", ":woman astronaut light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f680;"},
+ {"", ":woman astronaut medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f680;"},
+ {"", ":woman astronaut medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f680;"},
+ {"", ":woman astronaut medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f680;"},
+ {"", ":woman astronaut dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f680;"},
+ {"", ":man firefighter light skin tone:", "&#x1f468;&#x1f3fb;&#x200d;&#x1f692;"},
+ {"", ":man firefighter medium-light skin tone:", "&#x1f468;&#x1f3fc;&#x200d;&#x1f692;"},
+ {"", ":man firefighter medium skin tone:", "&#x1f468;&#x1f3fd;&#x200d;&#x1f692;"},
+ {"", ":man firefighter medium-dark skin tone:", "&#x1f468;&#x1f3fe;&#x200d;&#x1f692;"},
+ {"", ":man firefighter dark skin tone:", "&#x1f468;&#x1f3ff;&#x200d;&#x1f692;"},
+ {"", ":woman firefighter light skin tone:", "&#x1f469;&#x1f3fb;&#x200d;&#x1f692;"},
+ {"", ":woman firefighter medium-light skin tone:", "&#x1f469;&#x1f3fc;&#x200d;&#x1f692;"},
+ {"", ":woman firefighter medium skin tone:", "&#x1f469;&#x1f3fd;&#x200d;&#x1f692;"},
+ {"", ":woman firefighter medium-dark skin tone:", "&#x1f469;&#x1f3fe;&#x200d;&#x1f692;"},
+ {"", ":woman firefighter dark skin tone:", "&#x1f469;&#x1f3ff;&#x200d;&#x1f692;"},
+ {"", ":police officer light skin tone:", "&#x1f46e;&#x1f3fb;"},
+ {"", ":police officer medium-light skin tone:", "&#x1f46e;&#x1f3fc;"},
+ {"", ":police officer medium skin tone:", "&#x1f46e;&#x1f3fd;"},
+ {"", ":police officer medium-dark skin tone:", "&#x1f46e;&#x1f3fe;"},
+ {"", ":police officer dark skin tone:", "&#x1f46e;&#x1f3ff;"},
+ {"", ":man police officer light skin tone:", "&#x1f46e;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man police officer medium-light skin tone:", "&#x1f46e;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man police officer medium skin tone:", "&#x1f46e;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man police officer medium-dark skin tone:", "&#x1f46e;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man police officer dark skin tone:", "&#x1f46e;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman police officer light skin tone:", "&#x1f46e;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman police officer medium-light skin tone:", "&#x1f46e;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman police officer medium skin tone:", "&#x1f46e;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman police officer medium-dark skin tone:", "&#x1f46e;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman police officer dark skin tone:", "&#x1f46e;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":detective light skin tone:", "&#x1f575;&#x1f3fb;"},
+ {"", ":detective medium-light skin tone:", "&#x1f575;&#x1f3fc;"},
+ {"", ":detective medium skin tone:", "&#x1f575;&#x1f3fd;"},
+ {"", ":detective medium-dark skin tone:", "&#x1f575;&#x1f3fe;"},
+ {"", ":detective dark skin tone:", "&#x1f575;&#x1f3ff;"},
+ {"", ":man detective light skin tone:", "&#x1f575;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man detective medium-light skin tone:", "&#x1f575;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man detective medium skin tone:", "&#x1f575;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man detective medium-dark skin tone:", "&#x1f575;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man detective dark skin tone:", "&#x1f575;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman detective light skin tone:", "&#x1f575;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman detective medium-light skin tone:", "&#x1f575;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman detective medium skin tone:", "&#x1f575;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman detective medium-dark skin tone:", "&#x1f575;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman detective dark skin tone:", "&#x1f575;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":guard light skin tone:", "&#x1f482;&#x1f3fb;"},
+ {"", ":guard medium-light skin tone:", "&#x1f482;&#x1f3fc;"},
+ {"", ":guard medium skin tone:", "&#x1f482;&#x1f3fd;"},
+ {"", ":guard medium-dark skin tone:", "&#x1f482;&#x1f3fe;"},
+ {"", ":guard dark skin tone:", "&#x1f482;&#x1f3ff;"},
+ {"", ":man guard light skin tone:", "&#x1f482;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man guard medium-light skin tone:", "&#x1f482;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man guard medium skin tone:", "&#x1f482;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man guard medium-dark skin tone:", "&#x1f482;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man guard dark skin tone:", "&#x1f482;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman guard light skin tone:", "&#x1f482;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman guard medium-light skin tone:", "&#x1f482;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman guard medium skin tone:", "&#x1f482;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman guard medium-dark skin tone:", "&#x1f482;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman guard dark skin tone:", "&#x1f482;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":construction worker light skin tone:", "&#x1f477;&#x1f3fb;"},
+ {"", ":construction worker medium-light skin tone:", "&#x1f477;&#x1f3fc;"},
+ {"", ":construction worker medium skin tone:", "&#x1f477;&#x1f3fd;"},
+ {"", ":construction worker medium-dark skin tone:", "&#x1f477;&#x1f3fe;"},
+ {"", ":construction worker dark skin tone:", "&#x1f477;&#x1f3ff;"},
+ {"", ":man construction worker light skin tone:", "&#x1f477;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man construction worker medium-light skin tone:", "&#x1f477;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man construction worker medium skin tone:", "&#x1f477;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man construction worker medium-dark skin tone:", "&#x1f477;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man construction worker dark skin tone:", "&#x1f477;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman construction worker light skin tone:", "&#x1f477;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman construction worker medium-light skin tone:", "&#x1f477;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman construction worker medium skin tone:", "&#x1f477;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman construction worker medium-dark skin tone:", "&#x1f477;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman construction worker dark skin tone:", "&#x1f477;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":prince light skin tone:", "&#x1f934;&#x1f3fb;"},
+ {"", ":prince medium-light skin tone:", "&#x1f934;&#x1f3fc;"},
+ {"", ":prince medium skin tone:", "&#x1f934;&#x1f3fd;"},
+ {"", ":prince medium-dark skin tone:", "&#x1f934;&#x1f3fe;"},
+ {"", ":prince dark skin tone:", "&#x1f934;&#x1f3ff;"},
+ {"", ":princess light skin tone:", "&#x1f478;&#x1f3fb;"},
+ {"", ":princess medium-light skin tone:", "&#x1f478;&#x1f3fc;"},
+ {"", ":princess medium skin tone:", "&#x1f478;&#x1f3fd;"},
+ {"", ":princess medium-dark skin tone:", "&#x1f478;&#x1f3fe;"},
+ {"", ":princess dark skin tone:", "&#x1f478;&#x1f3ff;"},
+ {"", ":person wearing turban light skin tone:", "&#x1f473;&#x1f3fb;"},
+ {"", ":person wearing turban medium-light skin tone:", "&#x1f473;&#x1f3fc;"},
+ {"", ":person wearing turban medium skin tone:", "&#x1f473;&#x1f3fd;"},
+ {"", ":person wearing turban medium-dark skin tone:", "&#x1f473;&#x1f3fe;"},
+ {"", ":person wearing turban dark skin tone:", "&#x1f473;&#x1f3ff;"},
+ {"", ":man wearing turban light skin tone:", "&#x1f473;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man wearing turban medium-light skin tone:", "&#x1f473;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man wearing turban medium skin tone:", "&#x1f473;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man wearing turban medium-dark skin tone:", "&#x1f473;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man wearing turban dark skin tone:", "&#x1f473;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman wearing turban light skin tone:", "&#x1f473;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman wearing turban medium-light skin tone:", "&#x1f473;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman wearing turban medium skin tone:", "&#x1f473;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman wearing turban medium-dark skin tone:", "&#x1f473;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman wearing turban dark skin tone:", "&#x1f473;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":man with chinese cap light skin tone:", "&#x1f472;&#x1f3fb;"},
+ {"", ":man with chinese cap medium-light skin tone:", "&#x1f472;&#x1f3fc;"},
+ {"", ":man with chinese cap medium skin tone:", "&#x1f472;&#x1f3fd;"},
+ {"", ":man with chinese cap medium-dark skin tone:", "&#x1f472;&#x1f3fe;"},
+ {"", ":man with chinese cap dark skin tone:", "&#x1f472;&#x1f3ff;"},
+ {"", ":woman with headscarf light skin tone:", "&#x1f9d5;&#x1f3fb;"},
+ {"", ":woman with headscarf medium-light skin tone:", "&#x1f9d5;&#x1f3fc;"},
+ {"", ":woman with headscarf medium skin tone:", "&#x1f9d5;&#x1f3fd;"},
+ {"", ":woman with headscarf medium-dark skin tone:", "&#x1f9d5;&#x1f3fe;"},
+ {"", ":woman with headscarf dark skin tone:", "&#x1f9d5;&#x1f3ff;"},
+ {"", ":man in tuxedo light skin tone:", "&#x1f935;&#x1f3fb;"},
+ {"", ":man in tuxedo medium-light skin tone:", "&#x1f935;&#x1f3fc;"},
+ {"", ":man in tuxedo medium skin tone:", "&#x1f935;&#x1f3fd;"},
+ {"", ":man in tuxedo medium-dark skin tone:", "&#x1f935;&#x1f3fe;"},
+ {"", ":man in tuxedo dark skin tone:", "&#x1f935;&#x1f3ff;"},
+ {"", ":bride with veil light skin tone:", "&#x1f470;&#x1f3fb;"},
+ {"", ":bride with veil medium-light skin tone:", "&#x1f470;&#x1f3fc;"},
+ {"", ":bride with veil medium skin tone:", "&#x1f470;&#x1f3fd;"},
+ {"", ":bride with veil medium-dark skin tone:", "&#x1f470;&#x1f3fe;"},
+ {"", ":bride with veil dark skin tone:", "&#x1f470;&#x1f3ff;"},
+ {"", ":pregnant woman light skin tone:", "&#x1f930;&#x1f3fb;"},
+ {"", ":pregnant woman medium-light skin tone:", "&#x1f930;&#x1f3fc;"},
+ {"", ":pregnant woman medium skin tone:", "&#x1f930;&#x1f3fd;"},
+ {"", ":pregnant woman medium-dark skin tone:", "&#x1f930;&#x1f3fe;"},
+ {"", ":pregnant woman dark skin tone:", "&#x1f930;&#x1f3ff;"},
+ {"", ":breast-feeding light skin tone:", "&#x1f931;&#x1f3fb;"},
+ {"", ":breast-feeding medium-light skin tone:", "&#x1f931;&#x1f3fc;"},
+ {"", ":breast-feeding medium skin tone:", "&#x1f931;&#x1f3fd;"},
+ {"", ":breast-feeding medium-dark skin tone:", "&#x1f931;&#x1f3fe;"},
+ {"", ":breast-feeding dark skin tone:", "&#x1f931;&#x1f3ff;"},
+ {"", ":baby angel light skin tone:", "&#x1f47c;&#x1f3fb;"},
+ {"", ":baby angel medium-light skin tone:", "&#x1f47c;&#x1f3fc;"},
+ {"", ":baby angel medium skin tone:", "&#x1f47c;&#x1f3fd;"},
+ {"", ":baby angel medium-dark skin tone:", "&#x1f47c;&#x1f3fe;"},
+ {"", ":baby angel dark skin tone:", "&#x1f47c;&#x1f3ff;"},
+ {"", ":santa claus light skin tone:", "&#x1f385;&#x1f3fb;"},
+ {"", ":santa claus medium-light skin tone:", "&#x1f385;&#x1f3fc;"},
+ {"", ":santa claus medium skin tone:", "&#x1f385;&#x1f3fd;"},
+ {"", ":santa claus medium-dark skin tone:", "&#x1f385;&#x1f3fe;"},
+ {"", ":santa claus dark skin tone:", "&#x1f385;&#x1f3ff;"},
+ {"", ":mrs. claus light skin tone:", "&#x1f936;&#x1f3fb;"},
+ {"", ":mrs. claus medium-light skin tone:", "&#x1f936;&#x1f3fc;"},
+ {"", ":mrs. claus medium skin tone:", "&#x1f936;&#x1f3fd;"},
+ {"", ":mrs. claus medium-dark skin tone:", "&#x1f936;&#x1f3fe;"},
+ {"", ":mrs. claus dark skin tone:", "&#x1f936;&#x1f3ff;"},
+ {"", ":superhero light skin tone:", "&#x1f9b8;&#x1f3fb;"},
+ {"", ":superhero medium-light skin tone:", "&#x1f9b8;&#x1f3fc;"},
+ {"", ":superhero medium skin tone:", "&#x1f9b8;&#x1f3fd;"},
+ {"", ":superhero medium-dark skin tone:", "&#x1f9b8;&#x1f3fe;"},
+ {"", ":superhero dark skin tone:", "&#x1f9b8;&#x1f3ff;"},
+ {"", ":man superhero light skin tone:", "&#x1f9b8;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man superhero medium-light skin tone:", "&#x1f9b8;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man superhero medium skin tone:", "&#x1f9b8;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man superhero medium-dark skin tone:", "&#x1f9b8;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man superhero dark skin tone:", "&#x1f9b8;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman superhero light skin tone:", "&#x1f9b8;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman superhero medium-light skin tone:", "&#x1f9b8;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman superhero medium skin tone:", "&#x1f9b8;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman superhero medium-dark skin tone:", "&#x1f9b8;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman superhero dark skin tone:", "&#x1f9b8;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":supervillain light skin tone:", "&#x1f9b9;&#x1f3fb;"},
+ {"", ":supervillain medium-light skin tone:", "&#x1f9b9;&#x1f3fc;"},
+ {"", ":supervillain medium skin tone:", "&#x1f9b9;&#x1f3fd;"},
+ {"", ":supervillain medium-dark skin tone:", "&#x1f9b9;&#x1f3fe;"},
+ {"", ":supervillain dark skin tone:", "&#x1f9b9;&#x1f3ff;"},
+ {"", ":man supervillain light skin tone:", "&#x1f9b9;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man supervillain medium-light skin tone:", "&#x1f9b9;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man supervillain medium skin tone:", "&#x1f9b9;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man supervillain medium-dark skin tone:", "&#x1f9b9;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man supervillain dark skin tone:", "&#x1f9b9;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman supervillain light skin tone:", "&#x1f9b9;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman supervillain medium-light skin tone:", "&#x1f9b9;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman supervillain medium skin tone:", "&#x1f9b9;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman supervillain medium-dark skin tone:", "&#x1f9b9;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman supervillain dark skin tone:", "&#x1f9b9;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":mage light skin tone:", "&#x1f9d9;&#x1f3fb;"},
+ {"", ":mage medium-light skin tone:", "&#x1f9d9;&#x1f3fc;"},
+ {"", ":mage medium skin tone:", "&#x1f9d9;&#x1f3fd;"},
+ {"", ":mage medium-dark skin tone:", "&#x1f9d9;&#x1f3fe;"},
+ {"", ":mage dark skin tone:", "&#x1f9d9;&#x1f3ff;"},
+ {"", ":man mage light skin tone:", "&#x1f9d9;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man mage medium-light skin tone:", "&#x1f9d9;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man mage medium skin tone:", "&#x1f9d9;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man mage medium-dark skin tone:", "&#x1f9d9;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man mage dark skin tone:", "&#x1f9d9;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman mage light skin tone:", "&#x1f9d9;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman mage medium-light skin tone:", "&#x1f9d9;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman mage medium skin tone:", "&#x1f9d9;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman mage medium-dark skin tone:", "&#x1f9d9;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman mage dark skin tone:", "&#x1f9d9;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":fairy light skin tone:", "&#x1f9da;&#x1f3fb;"},
+ {"", ":fairy medium-light skin tone:", "&#x1f9da;&#x1f3fc;"},
+ {"", ":fairy medium skin tone:", "&#x1f9da;&#x1f3fd;"},
+ {"", ":fairy medium-dark skin tone:", "&#x1f9da;&#x1f3fe;"},
+ {"", ":fairy dark skin tone:", "&#x1f9da;&#x1f3ff;"},
+ {"", ":man fairy light skin tone:", "&#x1f9da;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man fairy medium-light skin tone:", "&#x1f9da;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man fairy medium skin tone:", "&#x1f9da;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man fairy medium-dark skin tone:", "&#x1f9da;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man fairy dark skin tone:", "&#x1f9da;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman fairy light skin tone:", "&#x1f9da;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman fairy medium-light skin tone:", "&#x1f9da;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman fairy medium skin tone:", "&#x1f9da;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman fairy medium-dark skin tone:", "&#x1f9da;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman fairy dark skin tone:", "&#x1f9da;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":vampire light skin tone:", "&#x1f9db;&#x1f3fb;"},
+ {"", ":vampire medium-light skin tone:", "&#x1f9db;&#x1f3fc;"},
+ {"", ":vampire medium skin tone:", "&#x1f9db;&#x1f3fd;"},
+ {"", ":vampire medium-dark skin tone:", "&#x1f9db;&#x1f3fe;"},
+ {"", ":vampire dark skin tone:", "&#x1f9db;&#x1f3ff;"},
+ {"", ":man vampire light skin tone:", "&#x1f9db;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man vampire medium-light skin tone:", "&#x1f9db;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man vampire medium skin tone:", "&#x1f9db;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man vampire medium-dark skin tone:", "&#x1f9db;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man vampire dark skin tone:", "&#x1f9db;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman vampire light skin tone:", "&#x1f9db;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman vampire medium-light skin tone:", "&#x1f9db;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman vampire medium skin tone:", "&#x1f9db;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman vampire medium-dark skin tone:", "&#x1f9db;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman vampire dark skin tone:", "&#x1f9db;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":merperson light skin tone:", "&#x1f9dc;&#x1f3fb;"},
+ {"", ":merperson medium-light skin tone:", "&#x1f9dc;&#x1f3fc;"},
+ {"", ":merperson medium skin tone:", "&#x1f9dc;&#x1f3fd;"},
+ {"", ":merperson medium-dark skin tone:", "&#x1f9dc;&#x1f3fe;"},
+ {"", ":merperson dark skin tone:", "&#x1f9dc;&#x1f3ff;"},
+ {"", ":merman light skin tone:", "&#x1f9dc;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":merman medium-light skin tone:", "&#x1f9dc;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":merman medium skin tone:", "&#x1f9dc;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":merman medium-dark skin tone:", "&#x1f9dc;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":merman dark skin tone:", "&#x1f9dc;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":mermaid light skin tone:", "&#x1f9dc;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":mermaid medium-light skin tone:", "&#x1f9dc;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":mermaid medium skin tone:", "&#x1f9dc;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":mermaid medium-dark skin tone:", "&#x1f9dc;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":mermaid dark skin tone:", "&#x1f9dc;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":elf light skin tone:", "&#x1f9dd;&#x1f3fb;"},
+ {"", ":elf medium-light skin tone:", "&#x1f9dd;&#x1f3fc;"},
+ {"", ":elf medium skin tone:", "&#x1f9dd;&#x1f3fd;"},
+ {"", ":elf medium-dark skin tone:", "&#x1f9dd;&#x1f3fe;"},
+ {"", ":elf dark skin tone:", "&#x1f9dd;&#x1f3ff;"},
+ {"", ":man elf light skin tone:", "&#x1f9dd;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man elf medium-light skin tone:", "&#x1f9dd;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man elf medium skin tone:", "&#x1f9dd;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man elf medium-dark skin tone:", "&#x1f9dd;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man elf dark skin tone:", "&#x1f9dd;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman elf light skin tone:", "&#x1f9dd;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman elf medium-light skin tone:", "&#x1f9dd;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman elf medium skin tone:", "&#x1f9dd;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman elf medium-dark skin tone:", "&#x1f9dd;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman elf dark skin tone:", "&#x1f9dd;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person getting massage light skin tone:", "&#x1f486;&#x1f3fb;"},
+ {"", ":person getting massage medium-light skin tone:", "&#x1f486;&#x1f3fc;"},
+ {"", ":person getting massage medium skin tone:", "&#x1f486;&#x1f3fd;"},
+ {"", ":person getting massage medium-dark skin tone:", "&#x1f486;&#x1f3fe;"},
+ {"", ":person getting massage dark skin tone:", "&#x1f486;&#x1f3ff;"},
+ {"", ":man getting massage light skin tone:", "&#x1f486;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man getting massage medium-light skin tone:", "&#x1f486;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man getting massage medium skin tone:", "&#x1f486;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man getting massage medium-dark skin tone:", "&#x1f486;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man getting massage dark skin tone:", "&#x1f486;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman getting massage light skin tone:", "&#x1f486;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman getting massage medium-light skin tone:", "&#x1f486;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman getting massage medium skin tone:", "&#x1f486;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman getting massage medium-dark skin tone:", "&#x1f486;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman getting massage dark skin tone:", "&#x1f486;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person getting haircut light skin tone:", "&#x1f487;&#x1f3fb;"},
+ {"", ":person getting haircut medium-light skin tone:", "&#x1f487;&#x1f3fc;"},
+ {"", ":person getting haircut medium skin tone:", "&#x1f487;&#x1f3fd;"},
+ {"", ":person getting haircut medium-dark skin tone:", "&#x1f487;&#x1f3fe;"},
+ {"", ":person getting haircut dark skin tone:", "&#x1f487;&#x1f3ff;"},
+ {"", ":man getting haircut light skin tone:", "&#x1f487;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man getting haircut medium-light skin tone:", "&#x1f487;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man getting haircut medium skin tone:", "&#x1f487;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man getting haircut medium-dark skin tone:", "&#x1f487;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man getting haircut dark skin tone:", "&#x1f487;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman getting haircut light skin tone:", "&#x1f487;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman getting haircut medium-light skin tone:", "&#x1f487;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman getting haircut medium skin tone:", "&#x1f487;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman getting haircut medium-dark skin tone:", "&#x1f487;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman getting haircut dark skin tone:", "&#x1f487;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person walking light skin tone:", "&#x1f6b6;&#x1f3fb;"},
+ {"", ":person walking medium-light skin tone:", "&#x1f6b6;&#x1f3fc;"},
+ {"", ":person walking medium skin tone:", "&#x1f6b6;&#x1f3fd;"},
+ {"", ":person walking medium-dark skin tone:", "&#x1f6b6;&#x1f3fe;"},
+ {"", ":person walking dark skin tone:", "&#x1f6b6;&#x1f3ff;"},
+ {"", ":man walking light skin tone:", "&#x1f6b6;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man walking medium-light skin tone:", "&#x1f6b6;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man walking medium skin tone:", "&#x1f6b6;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man walking medium-dark skin tone:", "&#x1f6b6;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man walking dark skin tone:", "&#x1f6b6;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman walking light skin tone:", "&#x1f6b6;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman walking medium-light skin tone:", "&#x1f6b6;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman walking medium skin tone:", "&#x1f6b6;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman walking medium-dark skin tone:", "&#x1f6b6;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman walking dark skin tone:", "&#x1f6b6;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person running light skin tone:", "&#x1f3c3;&#x1f3fb;"},
+ {"", ":person running medium-light skin tone:", "&#x1f3c3;&#x1f3fc;"},
+ {"", ":person running medium skin tone:", "&#x1f3c3;&#x1f3fd;"},
+ {"", ":person running medium-dark skin tone:", "&#x1f3c3;&#x1f3fe;"},
+ {"", ":person running dark skin tone:", "&#x1f3c3;&#x1f3ff;"},
+ {"", ":man running light skin tone:", "&#x1f3c3;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man running medium-light skin tone:", "&#x1f3c3;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man running medium skin tone:", "&#x1f3c3;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man running medium-dark skin tone:", "&#x1f3c3;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man running dark skin tone:", "&#x1f3c3;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman running light skin tone:", "&#x1f3c3;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman running medium-light skin tone:", "&#x1f3c3;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman running medium skin tone:", "&#x1f3c3;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman running medium-dark skin tone:", "&#x1f3c3;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman running dark skin tone:", "&#x1f3c3;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman dancing light skin tone:", "&#x1f483;&#x1f3fb;"},
+ {"", ":woman dancing medium-light skin tone:", "&#x1f483;&#x1f3fc;"},
+ {"", ":woman dancing medium skin tone:", "&#x1f483;&#x1f3fd;"},
+ {"", ":woman dancing medium-dark skin tone:", "&#x1f483;&#x1f3fe;"},
+ {"", ":woman dancing dark skin tone:", "&#x1f483;&#x1f3ff;"},
+ {"", ":man dancing light skin tone:", "&#x1f57a;&#x1f3fb;"},
+ {"", ":man dancing medium-light skin tone:", "&#x1f57a;&#x1f3fc;"},
+ {"", ":man dancing medium skin tone:", "&#x1f57a;&#x1f3fd;"},
+ {"", ":man dancing medium-dark skin tone:", "&#x1f57a;&#x1f3fe;"},
+ {"", ":man dancing dark skin tone:", "&#x1f57a;&#x1f3ff;"},
+ {"", ":man in suit levitating light skin tone:", "&#x1f574;&#x1f3fb;"},
+ {"", ":man in suit levitating medium-light skin tone:", "&#x1f574;&#x1f3fc;"},
+ {"", ":man in suit levitating medium skin tone:", "&#x1f574;&#x1f3fd;"},
+ {"", ":man in suit levitating medium-dark skin tone:", "&#x1f574;&#x1f3fe;"},
+ {"", ":man in suit levitating dark skin tone:", "&#x1f574;&#x1f3ff;"},
+ {"", ":person in steamy room light skin tone:", "&#x1f9d6;&#x1f3fb;"},
+ {"", ":person in steamy room medium-light skin tone:", "&#x1f9d6;&#x1f3fc;"},
+ {"", ":person in steamy room medium skin tone:", "&#x1f9d6;&#x1f3fd;"},
+ {"", ":person in steamy room medium-dark skin tone:", "&#x1f9d6;&#x1f3fe;"},
+ {"", ":person in steamy room dark skin tone:", "&#x1f9d6;&#x1f3ff;"},
+ {"", ":man in steamy room light skin tone:", "&#x1f9d6;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man in steamy room medium-light skin tone:", "&#x1f9d6;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man in steamy room medium skin tone:", "&#x1f9d6;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man in steamy room medium-dark skin tone:", "&#x1f9d6;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man in steamy room dark skin tone:", "&#x1f9d6;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman in steamy room light skin tone:", "&#x1f9d6;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman in steamy room medium-light skin tone:", "&#x1f9d6;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman in steamy room medium skin tone:", "&#x1f9d6;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman in steamy room medium-dark skin tone:", "&#x1f9d6;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman in steamy room dark skin tone:", "&#x1f9d6;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person climbing light skin tone:", "&#x1f9d7;&#x1f3fb;"},
+ {"", ":person climbing medium-light skin tone:", "&#x1f9d7;&#x1f3fc;"},
+ {"", ":person climbing medium skin tone:", "&#x1f9d7;&#x1f3fd;"},
+ {"", ":person climbing medium-dark skin tone:", "&#x1f9d7;&#x1f3fe;"},
+ {"", ":person climbing dark skin tone:", "&#x1f9d7;&#x1f3ff;"},
+ {"", ":man climbing light skin tone:", "&#x1f9d7;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man climbing medium-light skin tone:", "&#x1f9d7;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man climbing medium skin tone:", "&#x1f9d7;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man climbing medium-dark skin tone:", "&#x1f9d7;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man climbing dark skin tone:", "&#x1f9d7;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman climbing light skin tone:", "&#x1f9d7;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman climbing medium-light skin tone:", "&#x1f9d7;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman climbing medium skin tone:", "&#x1f9d7;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman climbing medium-dark skin tone:", "&#x1f9d7;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman climbing dark skin tone:", "&#x1f9d7;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":horse racing light skin tone:", "&#x1f3c7;&#x1f3fb;"},
+ {"", ":horse racing medium-light skin tone:", "&#x1f3c7;&#x1f3fc;"},
+ {"", ":horse racing medium skin tone:", "&#x1f3c7;&#x1f3fd;"},
+ {"", ":horse racing medium-dark skin tone:", "&#x1f3c7;&#x1f3fe;"},
+ {"", ":horse racing dark skin tone:", "&#x1f3c7;&#x1f3ff;"},
+ {"", ":snowboarder light skin tone:", "&#x1f3c2;&#x1f3fb;"},
+ {"", ":snowboarder medium-light skin tone:", "&#x1f3c2;&#x1f3fc;"},
+ {"", ":snowboarder medium skin tone:", "&#x1f3c2;&#x1f3fd;"},
+ {"", ":snowboarder medium-dark skin tone:", "&#x1f3c2;&#x1f3fe;"},
+ {"", ":snowboarder dark skin tone:", "&#x1f3c2;&#x1f3ff;"},
+ {"", ":person golfing light skin tone:", "&#x1f3cc;&#x1f3fb;"},
+ {"", ":person golfing medium-light skin tone:", "&#x1f3cc;&#x1f3fc;"},
+ {"", ":person golfing medium skin tone:", "&#x1f3cc;&#x1f3fd;"},
+ {"", ":person golfing medium-dark skin tone:", "&#x1f3cc;&#x1f3fe;"},
+ {"", ":person golfing dark skin tone:", "&#x1f3cc;&#x1f3ff;"},
+ {"", ":man golfing light skin tone:", "&#x1f3cc;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man golfing medium-light skin tone:", "&#x1f3cc;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man golfing medium skin tone:", "&#x1f3cc;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man golfing medium-dark skin tone:", "&#x1f3cc;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man golfing dark skin tone:", "&#x1f3cc;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman golfing light skin tone:", "&#x1f3cc;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman golfing medium-light skin tone:", "&#x1f3cc;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman golfing medium skin tone:", "&#x1f3cc;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman golfing medium-dark skin tone:", "&#x1f3cc;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman golfing dark skin tone:", "&#x1f3cc;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person surfing light skin tone:", "&#x1f3c4;&#x1f3fb;"},
+ {"", ":person surfing medium-light skin tone:", "&#x1f3c4;&#x1f3fc;"},
+ {"", ":person surfing medium skin tone:", "&#x1f3c4;&#x1f3fd;"},
+ {"", ":person surfing medium-dark skin tone:", "&#x1f3c4;&#x1f3fe;"},
+ {"", ":person surfing dark skin tone:", "&#x1f3c4;&#x1f3ff;"},
+ {"", ":man surfing light skin tone:", "&#x1f3c4;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man surfing medium-light skin tone:", "&#x1f3c4;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man surfing medium skin tone:", "&#x1f3c4;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man surfing medium-dark skin tone:", "&#x1f3c4;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man surfing dark skin tone:", "&#x1f3c4;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman surfing light skin tone:", "&#x1f3c4;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman surfing medium-light skin tone:", "&#x1f3c4;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman surfing medium skin tone:", "&#x1f3c4;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman surfing medium-dark skin tone:", "&#x1f3c4;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman surfing dark skin tone:", "&#x1f3c4;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person rowing boat light skin tone:", "&#x1f6a3;&#x1f3fb;"},
+ {"", ":person rowing boat medium-light skin tone:", "&#x1f6a3;&#x1f3fc;"},
+ {"", ":person rowing boat medium skin tone:", "&#x1f6a3;&#x1f3fd;"},
+ {"", ":person rowing boat medium-dark skin tone:", "&#x1f6a3;&#x1f3fe;"},
+ {"", ":person rowing boat dark skin tone:", "&#x1f6a3;&#x1f3ff;"},
+ {"", ":man rowing boat light skin tone:", "&#x1f6a3;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man rowing boat medium-light skin tone:", "&#x1f6a3;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man rowing boat medium skin tone:", "&#x1f6a3;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man rowing boat medium-dark skin tone:", "&#x1f6a3;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man rowing boat dark skin tone:", "&#x1f6a3;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman rowing boat light skin tone:", "&#x1f6a3;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman rowing boat medium-light skin tone:", "&#x1f6a3;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman rowing boat medium skin tone:", "&#x1f6a3;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman rowing boat medium-dark skin tone:", "&#x1f6a3;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman rowing boat dark skin tone:", "&#x1f6a3;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person swimming light skin tone:", "&#x1f3ca;&#x1f3fb;"},
+ {"", ":person swimming medium-light skin tone:", "&#x1f3ca;&#x1f3fc;"},
+ {"", ":person swimming medium skin tone:", "&#x1f3ca;&#x1f3fd;"},
+ {"", ":person swimming medium-dark skin tone:", "&#x1f3ca;&#x1f3fe;"},
+ {"", ":person swimming dark skin tone:", "&#x1f3ca;&#x1f3ff;"},
+ {"", ":man swimming light skin tone:", "&#x1f3ca;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man swimming medium-light skin tone:", "&#x1f3ca;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man swimming medium skin tone:", "&#x1f3ca;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man swimming medium-dark skin tone:", "&#x1f3ca;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man swimming dark skin tone:", "&#x1f3ca;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman swimming light skin tone:", "&#x1f3ca;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman swimming medium-light skin tone:", "&#x1f3ca;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman swimming medium skin tone:", "&#x1f3ca;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman swimming medium-dark skin tone:", "&#x1f3ca;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman swimming dark skin tone:", "&#x1f3ca;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person bouncing ball light skin tone:", "&#x26f9;&#x1f3fb;"},
+ {"", ":person bouncing ball medium-light skin tone:", "&#x26f9;&#x1f3fc;"},
+ {"", ":person bouncing ball medium skin tone:", "&#x26f9;&#x1f3fd;"},
+ {"", ":person bouncing ball medium-dark skin tone:", "&#x26f9;&#x1f3fe;"},
+ {"", ":person bouncing ball dark skin tone:", "&#x26f9;&#x1f3ff;"},
+ {"", ":man bouncing ball light skin tone:", "&#x26f9;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man bouncing ball medium-light skin tone:", "&#x26f9;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man bouncing ball medium skin tone:", "&#x26f9;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man bouncing ball medium-dark skin tone:", "&#x26f9;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man bouncing ball dark skin tone:", "&#x26f9;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman bouncing ball light skin tone:", "&#x26f9;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman bouncing ball medium-light skin tone:", "&#x26f9;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman bouncing ball medium skin tone:", "&#x26f9;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman bouncing ball medium-dark skin tone:", "&#x26f9;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman bouncing ball dark skin tone:", "&#x26f9;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person lifting weights light skin tone:", "&#x1f3cb;&#x1f3fb;"},
+ {"", ":person lifting weights medium-light skin tone:", "&#x1f3cb;&#x1f3fc;"},
+ {"", ":person lifting weights medium skin tone:", "&#x1f3cb;&#x1f3fd;"},
+ {"", ":person lifting weights medium-dark skin tone:", "&#x1f3cb;&#x1f3fe;"},
+ {"", ":person lifting weights dark skin tone:", "&#x1f3cb;&#x1f3ff;"},
+ {"", ":man lifting weights light skin tone:", "&#x1f3cb;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man lifting weights medium-light skin tone:", "&#x1f3cb;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man lifting weights medium skin tone:", "&#x1f3cb;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man lifting weights medium-dark skin tone:", "&#x1f3cb;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man lifting weights dark skin tone:", "&#x1f3cb;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman lifting weights light skin tone:", "&#x1f3cb;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman lifting weights medium-light skin tone:", "&#x1f3cb;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman lifting weights medium skin tone:", "&#x1f3cb;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman lifting weights medium-dark skin tone:", "&#x1f3cb;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman lifting weights dark skin tone:", "&#x1f3cb;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person biking light skin tone:", "&#x1f6b4;&#x1f3fb;"},
+ {"", ":person biking medium-light skin tone:", "&#x1f6b4;&#x1f3fc;"},
+ {"", ":person biking medium skin tone:", "&#x1f6b4;&#x1f3fd;"},
+ {"", ":person biking medium-dark skin tone:", "&#x1f6b4;&#x1f3fe;"},
+ {"", ":person biking dark skin tone:", "&#x1f6b4;&#x1f3ff;"},
+ {"", ":man biking light skin tone:", "&#x1f6b4;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man biking medium-light skin tone:", "&#x1f6b4;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man biking medium skin tone:", "&#x1f6b4;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man biking medium-dark skin tone:", "&#x1f6b4;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man biking dark skin tone:", "&#x1f6b4;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman biking light skin tone:", "&#x1f6b4;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman biking medium-light skin tone:", "&#x1f6b4;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman biking medium skin tone:", "&#x1f6b4;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman biking medium-dark skin tone:", "&#x1f6b4;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman biking dark skin tone:", "&#x1f6b4;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person mountain biking light skin tone:", "&#x1f6b5;&#x1f3fb;"},
+ {"", ":person mountain biking medium-light skin tone:", "&#x1f6b5;&#x1f3fc;"},
+ {"", ":person mountain biking medium skin tone:", "&#x1f6b5;&#x1f3fd;"},
+ {"", ":person mountain biking medium-dark skin tone:", "&#x1f6b5;&#x1f3fe;"},
+ {"", ":person mountain biking dark skin tone:", "&#x1f6b5;&#x1f3ff;"},
+ {"", ":man mountain biking light skin tone:", "&#x1f6b5;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man mountain biking medium-light skin tone:", "&#x1f6b5;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man mountain biking medium skin tone:", "&#x1f6b5;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man mountain biking medium-dark skin tone:", "&#x1f6b5;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man mountain biking dark skin tone:", "&#x1f6b5;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman mountain biking light skin tone:", "&#x1f6b5;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman mountain biking medium-light skin tone:", "&#x1f6b5;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman mountain biking medium skin tone:", "&#x1f6b5;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman mountain biking medium-dark skin tone:", "&#x1f6b5;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman mountain biking dark skin tone:", "&#x1f6b5;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person cartwheeling light skin tone:", "&#x1f938;&#x1f3fb;"},
+ {"", ":person cartwheeling medium-light skin tone:", "&#x1f938;&#x1f3fc;"},
+ {"", ":person cartwheeling medium skin tone:", "&#x1f938;&#x1f3fd;"},
+ {"", ":person cartwheeling medium-dark skin tone:", "&#x1f938;&#x1f3fe;"},
+ {"", ":person cartwheeling dark skin tone:", "&#x1f938;&#x1f3ff;"},
+ {"", ":man cartwheeling light skin tone:", "&#x1f938;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man cartwheeling medium-light skin tone:", "&#x1f938;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man cartwheeling medium skin tone:", "&#x1f938;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man cartwheeling medium-dark skin tone:", "&#x1f938;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man cartwheeling dark skin tone:", "&#x1f938;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman cartwheeling light skin tone:", "&#x1f938;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman cartwheeling medium-light skin tone:", "&#x1f938;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman cartwheeling medium skin tone:", "&#x1f938;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman cartwheeling medium-dark skin tone:", "&#x1f938;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman cartwheeling dark skin tone:", "&#x1f938;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person playing water polo light skin tone:", "&#x1f93d;&#x1f3fb;"},
+ {"", ":person playing water polo medium-light skin tone:", "&#x1f93d;&#x1f3fc;"},
+ {"", ":person playing water polo medium skin tone:", "&#x1f93d;&#x1f3fd;"},
+ {"", ":person playing water polo medium-dark skin tone:", "&#x1f93d;&#x1f3fe;"},
+ {"", ":person playing water polo dark skin tone:", "&#x1f93d;&#x1f3ff;"},
+ {"", ":man playing water polo light skin tone:", "&#x1f93d;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man playing water polo medium-light skin tone:", "&#x1f93d;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man playing water polo medium skin tone:", "&#x1f93d;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man playing water polo medium-dark skin tone:", "&#x1f93d;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man playing water polo dark skin tone:", "&#x1f93d;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman playing water polo light skin tone:", "&#x1f93d;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman playing water polo medium-light skin tone:", "&#x1f93d;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman playing water polo medium skin tone:", "&#x1f93d;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman playing water polo medium-dark skin tone:", "&#x1f93d;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman playing water polo dark skin tone:", "&#x1f93d;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person playing handball light skin tone:", "&#x1f93e;&#x1f3fb;"},
+ {"", ":person playing handball medium-light skin tone:", "&#x1f93e;&#x1f3fc;"},
+ {"", ":person playing handball medium skin tone:", "&#x1f93e;&#x1f3fd;"},
+ {"", ":person playing handball medium-dark skin tone:", "&#x1f93e;&#x1f3fe;"},
+ {"", ":person playing handball dark skin tone:", "&#x1f93e;&#x1f3ff;"},
+ {"", ":man playing handball light skin tone:", "&#x1f93e;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man playing handball medium-light skin tone:", "&#x1f93e;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man playing handball medium skin tone:", "&#x1f93e;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man playing handball medium-dark skin tone:", "&#x1f93e;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man playing handball dark skin tone:", "&#x1f93e;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman playing handball light skin tone:", "&#x1f93e;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman playing handball medium-light skin tone:", "&#x1f93e;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman playing handball medium skin tone:", "&#x1f93e;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman playing handball medium-dark skin tone:", "&#x1f93e;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman playing handball dark skin tone:", "&#x1f93e;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person juggling light skin tone:", "&#x1f939;&#x1f3fb;"},
+ {"", ":person juggling medium-light skin tone:", "&#x1f939;&#x1f3fc;"},
+ {"", ":person juggling medium skin tone:", "&#x1f939;&#x1f3fd;"},
+ {"", ":person juggling medium-dark skin tone:", "&#x1f939;&#x1f3fe;"},
+ {"", ":person juggling dark skin tone:", "&#x1f939;&#x1f3ff;"},
+ {"", ":man juggling light skin tone:", "&#x1f939;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man juggling medium-light skin tone:", "&#x1f939;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man juggling medium skin tone:", "&#x1f939;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man juggling medium-dark skin tone:", "&#x1f939;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man juggling dark skin tone:", "&#x1f939;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman juggling light skin tone:", "&#x1f939;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman juggling medium-light skin tone:", "&#x1f939;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman juggling medium skin tone:", "&#x1f939;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman juggling medium-dark skin tone:", "&#x1f939;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman juggling dark skin tone:", "&#x1f939;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person in lotus position light skin tone:", "&#x1f9d8;&#x1f3fb;"},
+ {"", ":person in lotus position medium-light skin tone:", "&#x1f9d8;&#x1f3fc;"},
+ {"", ":person in lotus position medium skin tone:", "&#x1f9d8;&#x1f3fd;"},
+ {"", ":person in lotus position medium-dark skin tone:", "&#x1f9d8;&#x1f3fe;"},
+ {"", ":person in lotus position dark skin tone:", "&#x1f9d8;&#x1f3ff;"},
+ {"", ":man in lotus position light skin tone:", "&#x1f9d8;&#x1f3fb;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man in lotus position medium-light skin tone:", "&#x1f9d8;&#x1f3fc;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man in lotus position medium skin tone:", "&#x1f9d8;&#x1f3fd;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man in lotus position medium-dark skin tone:", "&#x1f9d8;&#x1f3fe;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":man in lotus position dark skin tone:", "&#x1f9d8;&#x1f3ff;&#x200d;&#x2642;&#xfe0f;"},
+ {"", ":woman in lotus position light skin tone:", "&#x1f9d8;&#x1f3fb;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman in lotus position medium-light skin tone:", "&#x1f9d8;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman in lotus position medium skin tone:", "&#x1f9d8;&#x1f3fd;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman in lotus position medium-dark skin tone:", "&#x1f9d8;&#x1f3fe;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":woman in lotus position dark skin tone:", "&#x1f9d8;&#x1f3ff;&#x200d;&#x2640;&#xfe0f;"},
+ {"", ":person taking bath light skin tone:", "&#x1f6c0;&#x1f3fb;"},
+ {"", ":person taking bath medium-light skin tone:", "&#x1f6c0;&#x1f3fc;"},
+ {"", ":person taking bath medium skin tone:", "&#x1f6c0;&#x1f3fd;"},
+ {"", ":person taking bath medium-dark skin tone:", "&#x1f6c0;&#x1f3fe;"},
+ {"", ":person taking bath dark skin tone:", "&#x1f6c0;&#x1f3ff;"},
+ {"", ":person in bed light skin tone:", "&#x1f6cc;&#x1f3fb;"},
+ {"", ":person in bed medium-light skin tone:", "&#x1f6cc;&#x1f3fc;"},
+ {"", ":person in bed medium skin tone:", "&#x1f6cc;&#x1f3fd;"},
+ {"", ":person in bed medium-dark skin tone:", "&#x1f6cc;&#x1f3fe;"},
+ {"", ":person in bed dark skin tone:", "&#x1f6cc;&#x1f3ff;"},
+ {"", ":light skin tone:", "&#x1f3fb;"},
+ {"", ":medium-light skin tone:", "&#x1f3fc;"},
+ {"", ":medium skin tone:", "&#x1f3fd;"},
+ {"", ":medium-dark skin tone:", "&#x1f3fe;"},
+ {"", ":dark skin tone:", "&#x1f3ff;"},
+}
+;
+
+static const int g_numEmojiEntities = (int)(sizeof(g_emojiEntities)/ sizeof(*g_emojiEntities));
+
+EmojiEntityMapper *EmojiEntityMapper::s_instance = 0;
+
+EmojiEntityMapper::EmojiEntityMapper()
+{
+ m_name2symGh = new QDict<int>(1009);
+ m_name2symUni = new QDict<int>(1009);
+ m_name2symStripUni = new QDict<int>(10);
+ m_name2symGh->setAutoDelete(TRUE);
+ m_name2symUni->setAutoDelete(TRUE);
+ m_name2symStripUni->setAutoDelete(TRUE);
+ // 2 loops to be able to give precedence to the unicodeName (CLDR)
+ for (int i = 0; i < g_numEmojiEntities; i++)
+ {
+ if (strlen(g_emojiEntities[i].githubName)) m_name2symGh->insert(g_emojiEntities[i].githubName, new int(i+1));
+ }
+ for (int i = 0; i < g_numEmojiEntities; i++)
+ {
+ m_name2symUni->insert(g_emojiEntities[i].unicodeName, new int(-(i+1)));
+ QCString strippedUnicodeName = g_emojiEntities[i].unicodeName;
+ // A ring -> a ring
+ strippedUnicodeName = substitute(strippedUnicodeName,"\xc3\x85","\xc3\xa5");
+ if (strippedUnicodeName != g_emojiEntities[i].unicodeName)
+ {
+ m_name2symStripUni->insert(strippedUnicodeName, new int(-(i+1)));
+ }
+ // a ring -> a
+ strippedUnicodeName = substitute(strippedUnicodeName,"\xc3\xa5","a");
+ // c cedille -> c
+ strippedUnicodeName = substitute(strippedUnicodeName,"\xc3\xa7","c");
+ // o circumflex -> o
+ strippedUnicodeName = substitute(strippedUnicodeName,"\xc3\xb4","o");
+ // e acute -> e
+ strippedUnicodeName = substitute(strippedUnicodeName,"\xc3\xa9","e");
+ // a tilde -> a
+ strippedUnicodeName = substitute(strippedUnicodeName,"\xc3\xa3","a");
+ // i acute -> i
+ strippedUnicodeName = substitute(strippedUnicodeName,"\xc3\xad","i");
+ if (strippedUnicodeName != g_emojiEntities[i].unicodeName)
+ {
+ m_name2symStripUni->insert(strippedUnicodeName, new int(-(i+1)));
+ }
+ }
+}
+
+EmojiEntityMapper::~EmojiEntityMapper()
+{
+ delete m_name2symGh;
+ delete m_name2symUni;
+ delete m_name2symStripUni;
+}
+
+/** Returns the one and only instance of the Emoji entity mapper */
+EmojiEntityMapper *EmojiEntityMapper::instance()
+{
+ if (s_instance==0)
+ {
+ s_instance = new EmojiEntityMapper;
+ }
+ return s_instance;
+}
+
+/** Deletes the one and only instance of the Emoji entity mapper */
+void EmojiEntityMapper::deleteInstance()
+{
+ delete s_instance;
+ s_instance=0;
+}
+
+
+/*! @brief Access routine to the UTF8 code of the Emoji entity
+ *
+ * @param symb Code of the requested Emoji entity
+ * @param useInPrintf If TRUE the result will be escaped such that it can be
+ * used in a printf string pattern
+ * @return the UTF8 code of the Emoji entity,
+ * in case the UTF code is unknown \c NULL is returned.
+ */
+const char *EmojiEntityMapper::utf8(int symb) const
+{
+ if (symb > 0) return g_emojiEntities[symb-1].githubName;
+ else if (symb < 0) return g_emojiEntities[abs(symb)-1].unicodeName;
+ else return NULL;
+}
+
+/*! @brief Access routine to the html code of the Emoji entity
+ *
+ * @param symb Code of the requested Emoji entity
+ * @param useInPrintf If TRUE the result will be escaped such that it can be
+ * used in a printf string pattern
+ * @return the html representation of the Emoji entity,
+ * in case the html code is unknown \c NULL is returned.
+ */
+const char *EmojiEntityMapper::html(int symb) const
+{
+ return g_emojiEntities[abs(symb) - 1].code;
+}
+
+/*! @brief Access routine to the XML code of the Emoji entity
+ *
+ * @param symb Code of the requested Emoji entity
+ * @return the XML code of the Emoji entity,
+ * in case the XML code is unknown \c NULL is returned.
+ */
+const char *EmojiEntityMapper::xml(int symb) const
+{
+ return g_emojiEntities[abs(symb) - 1].code;
+}
+/*! @brief Access routine to the docbook code of the Emoji entity
+ *
+ * @param symb Code of the requested Emoji entity
+ * @return the docbook code of the Emoji entity,
+ * in case the docbook code is unknown \c NULL is returned.
+ */
+const char *EmojiEntityMapper::docbook(int symb) const
+{
+ return g_emojiEntities[abs(symb) - 1].code;
+}
+
+/*! @brief Access routine to the LaTeX code of the Emoji entity
+ *
+ * @param symb Code of the requested Emoji entity
+ * @return the LaTeX code of the Emoji entity,
+ * in case the LaTeX code is unknown \c NULL is returned.
+ */
+const char *EmojiEntityMapper::latex(int symb) const
+{
+ if (symb > 0) return g_emojiEntities[symb-1].githubName;
+ else if (symb < 0) return g_emojiEntities[abs(symb)-1].unicodeName;
+ else return NULL;
+}
+
+/*! @brief Access routine to the man code of the Emoji entity
+ *
+ * @param symb Code of the requested Emoji entity
+ * @return the man of the Emoji entity,
+ * in case the man code is unknown \c NULL is returned.
+ */
+const char *EmojiEntityMapper::man(int symb) const
+{
+ if (symb > 0) return g_emojiEntities[symb-1].githubName;
+ else if (symb < 0) return g_emojiEntities[abs(symb)-1].unicodeName;
+ else return NULL;
+}
+
+/*! @brief Access routine to the RTF code of the Emoji entity
+ *
+ * @param symb Code of the requested Emoji entity
+ * @return the RTF of the Emoji entity,
+ * in case the RTF code is unknown \c NULL is returned.
+ */
+const char *EmojiEntityMapper::rtf(int symb) const
+{
+ return g_emojiEntities[abs(symb) - 1].code;
+}
+
+/*! @brief Access routine to the perl struct with the perl code of the Emoji entity
+ *
+ * @param symb Code of the requested Emoji entity
+ * @return the pointer to perl struct with the perl code of the Emoji entity,
+ * in case the perl code does not exists the NULL pointer is entered in the
+ * \c symb field and in the `DocSymbol::Perl_unknown` in the \c type field.
+ */
+const char *EmojiEntityMapper::perl(int symb) const
+{
+ if (symb > 0) return g_emojiEntities[symb-1].githubName;
+ else if (symb < 0) return g_emojiEntities[abs(symb)-1].unicodeName;
+ else return NULL;
+}
+
+/*!
+ * @brief Give code of the requested Emoji entity name
+ * @param symName Emoji entity name
+ * @return the code for the requested Emoji entity name,
+ * in case the requested Emoji item does not exist `0` is returned.
+ */
+int EmojiEntityMapper::name2sym(const QCString &symName) const
+{
+ QCString locSymName = symName.lower();
+ int *pSymb = m_name2symUni->find(locSymName);
+ if (!pSymb) pSymb = m_name2symStripUni->find(locSymName);
+ if (!pSymb) pSymb = m_name2symGh->find(locSymName);
+ return pSymb ? (*pSymb) : 0;
+}
+void EmojiEntityMapper::writeEmojiFile(QFile &file)
+{
+ FTextStream t(&file);
+
+ for (int i = 0; i < g_numEmojiEntities; i++)
+ {
+ t << g_emojiEntities[i].unicodeName << endl;
+ }
+ for (int i = 0; i < g_numEmojiEntities; i++)
+ {
+ if (strlen(g_emojiEntities[i].githubName)) t << g_emojiEntities[i].githubName << endl;
+ }
+}
+/*! @brief Access routine to the code of the Emoji entity
+ *
+ * @param symb Code of the requested Emoji entity
+ * @return the code of the Emoji entity,
+ */
+const char *EmojiEntityMapper::code(int symb) const
+{
+ return g_emojiEntities[abs(symb) - 1].code;
+}
+
+/*! @brief Access routine to the text of the Emoji entity
+ *
+ * @param symb Code of the requested Emoji entity
+ * @return the text of the Emoji entity,
+ */
+const char *EmojiEntityMapper::text(int symb) const
+{
+ if (symb > 0) return g_emojiEntities[symb-1].githubName;
+ else if (symb < 0) return g_emojiEntities[abs(symb)-1].unicodeName;
+ else return NULL;
+}
+/// \file
+/// to generate the content of the table with the emoji definitions and code the following procedure has been used:
+///
+/// <pre>
+/// wget https://api.github.com/emojis
+/// wget https://www.unicode.org/emoji/charts/full-emoji-list.html
+/// wget http://www.unicode.org/emoji/charts/full-emoji-modifiers.html
+///
+/// grep -v "[{}]" emojis | sed -e "s/https:.*\///" | sed -e "s%.png.*%%" | sed -e "s/ //" | sed -e "s/://" | tr ' ' '\n' | tr '\042' ' ' | sed -e "s/ //g" > emojis.res
+///
+/// grep -A 14 "<tr><td class='rchars'>[0-9]" full-emoji-list.html | grep -v "class='andr" | grep -v "class='[r]*chars'" | sed -e "s/<[^>]*>//g" | sed -e "s/://" | tr [A-Z] [a-z] | sed -e "s/^[^a-z][^a-z][^a-z] //" | grep -v "\-\-" | sed -e "s/&amp;/\&/" | sed -e "s/ u+/;\&#x/g" | sed -e "s/^u+\(.*\)/\&#x\1;/" > full.res
+/// grep -A 14 "<tr><td class='rchars'>[0-9]" full-emoji-modifiers.html | grep -v "class='andr" | grep -v "class='[r]*chars'" | sed -e "s/<[^>]*>//g" | sed -e "s/://" | tr [A-Z] [a-z] | sed -e "s/^[^a-z][^a-z][^a-z] //" | grep -v "\-\-" | sed -e "s/&amp;/\&/" | sed -e "s/ u+/;\&#x/g" | sed -e "s/^u+\(.*\)/\&#x\1;/" >> full.res
+///
+///
+/// python transform.py full.res emojis.res > transform.res
+/// </pre>
+/// where the contents of `transform.py` is:
+/// \code{.py}
+///import sys
+///
+///# read first file (unicode names)
+///# read second files (github names)
+///
+///uniFile = open(sys.argv[1])
+///emoFile = open(sys.argv[2])
+///
+///uniLines = uniFile.readlines()
+///emoLines = emoFile.readlines()
+///
+///uniFile.close()
+///emoFile.close()
+///
+///uniMaxLen = 0
+///emoMaxLen = 0
+///
+///for i in range(0, len(uniLines), 2):
+/// if (len(uniLines[i]) > uniMaxLen):
+/// uniMaxLen = len(uniLines[i])
+///
+///for i in range(0, len(emoLines), 2):
+/// if (len(emoLines[i]) > emoMaxLen):
+/// emoMaxLen = len(emoLines[i])
+///
+///uniProcessed = [False]*(len(uniLines) / 2)
+///
+///# replace "strange" single and double quotes.
+///for i in range(0, len(uniLines), 2):
+/// uniLines[i+1] = uniLines[i+1].replace("\342\200\234",'\\"').replace("\342\200\235",'\\"')
+/// uniLines[i+1] = uniLines[i+1].replace("\342\200\231","'").replace("\342\200\231","'")
+///
+///for i in range(0, len(emoLines), 2):
+/// emoCode = emoLines[i+1].split('-')
+/// found = False
+/// emoCode = [e.replace('\n', '') for e in emoCode]
+/// for u in range(0, len(uniLines), 2):
+/// cnt = 0
+/// beg = 0
+/// for j in emoCode:
+/// pos = uniLines[u].find(j, beg)
+/// if pos != -1:
+/// # in case of 'u+': 2, '&#x': 3
+/// if (beg == 0 and j == emoCode[0] and pos != 3):
+/// break
+/// cnt += 1
+/// beg = pos + 1
+/// if (cnt == len(emoCode)):
+/// uniProcessed[u/2] = True
+/// found = True
+/// print ' {":'+emoLines[i].replace('\n','')+':",'+(emoMaxLen-len(emoLines[i].replace('\n',''))+1)*' '+'":'+uniLines[u+1].replace('\n','')+':",'+(uniMaxLen-len(uniLines[u+1].replace('\n',''))+1)*' '+'"'+uniLines[u].replace('\n','')+'"},'
+/// break
+/// if not found:
+/// # github name but no unicode version
+/// # print ' ONLY_GITHUB_NAME "'+emoLines[i].replace('\n','')+'" "'+emoLines[i+1].replace('\n','')+'"'
+/// pass
+///
+///for u in range(0, len(uniProcessed)):
+/// if not uniProcessed[u]:
+/// print ' {"",'+(emoMaxLen+1)*' '+'":'+uniLines[u*2+1].replace('\n','')+':",'+(uniMaxLen-len(uniLines[u*2+1].replace('\n',''))+1)*' '+'"'+uniLines[u*2].replace('\n','')+'"},'
+///
+/// \endcode
diff --git a/src/emoji.h b/src/emoji.h
new file mode 100644
index 0000000..b8db6f1
--- /dev/null
+++ b/src/emoji.h
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1997-2018 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 EMOJIENTITY_H
+#define EMOJIENTITY_H
+
+#include <qdict.h>
+#include <qfile.h>
+
+class FTextStream;
+
+/** @brief Singleton helper class to map emoji entities to other formats */
+class EmojiEntityMapper
+{
+ public:
+ static EmojiEntityMapper *instance();
+ static void deleteInstance();
+ int name2sym(const QCString &symName) const;
+ const char *utf8(int symb) const;
+ const char *html(int symb) const;
+ const char *xml(int symb) const;
+ const char *docbook(int symb) const;
+ const char *latex(int symb) const;
+ const char *man(int symb) const;
+ const char *rtf(int symb) const;
+ const char *perl(int symb) const;
+ const char *code(int symb) const;
+ const char *text(int symb) const;
+ void writeEmojiFile(QFile &file);
+ private:
+ EmojiEntityMapper();
+ ~EmojiEntityMapper();
+ static EmojiEntityMapper *s_instance;
+ QDict<int> *m_name2symGh;
+ QDict<int> *m_name2symUni;
+ QDict<int> *m_name2symStripUni;
+};
+
+#endif
diff --git a/src/entry.cpp b/src/entry.cpp
index a0460da..15c6fec 100644
--- a/src/entry.cpp
+++ b/src/entry.cpp
@@ -79,6 +79,8 @@ Entry::Entry(const Entry &e)
subGrouping = e.subGrouping;
callGraph = e.callGraph;
callerGraph = e.callerGraph;
+ referencedByRelation = e.referencedByRelation;
+ referencesRelation = e.referencesRelation;
virt = e.virt;
args = e.args;
bitfields = e.bitfields;
@@ -219,6 +221,8 @@ void Entry::reset()
{
static bool entryCallGraph = Config_getBool(CALL_GRAPH);
static bool entryCallerGraph = Config_getBool(CALLER_GRAPH);
+ static bool entryReferencedByRelation = Config_getBool(REFERENCED_BY_RELATION);
+ static bool entryReferencesRelation = Config_getBool(REFERENCES_RELATION);
//printf("Entry::reset()\n");
name.resize(0);
type.resize(0);
@@ -250,6 +254,8 @@ void Entry::reset()
mGrpId = -1;
callGraph = entryCallGraph;
callerGraph = entryCallerGraph;
+ referencedByRelation = entryReferencedByRelation;
+ referencesRelation = entryReferencesRelation;
section = EMPTY_SEC;
mtype = Method;
virt = Normal;
@@ -264,6 +270,7 @@ void Entry::reset()
protection = Public;
groupDocType = GROUPDOC_NORMAL;
id.resize(0);
+ metaData.resize(0);
m_sublist->clear();
extends->clear();
groups->clear();
diff --git a/src/entry.h b/src/entry.h
index 739b128..44e47da 100644
--- a/src/entry.h
+++ b/src/entry.h
@@ -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.
*
@@ -33,21 +33,21 @@ class ArgumentList;
struct ListItemInfo;
/** This class stores information about an inheritance relation
- */
-struct BaseInfo
+ */
+struct BaseInfo
{
/*! Creates an object representing an inheritance relation */
- BaseInfo(const char *n,Protection p,Specifier v) :
+ BaseInfo(const char *n,Protection p,Specifier v) :
name(n),prot(p),virt(v) {}
QCString name; //!< the name of the base class
Protection prot; //!< inheritance type
Specifier virt; //!< virtualness
};
-/** This struct is used to capture the tag file information
- * for an Entry.
+/** This struct is used to capture the tag file information
+ * for an Entry.
*/
-struct TagInfo
+struct TagInfo
{
QCString tagName;
QCString fileName;
@@ -55,7 +55,7 @@ struct TagInfo
};
/** Represents an unstructured piece of information, about an
- * entity found in the sources.
+ * entity found in the sources.
*
* parseMain() in scanner.l will generate a tree of these
* entries.
@@ -65,13 +65,13 @@ class Entry
public:
/*! Kind of entries that are supported */
- enum Sections {
- CLASS_SEC = 0x00000001,
+ enum Sections {
+ CLASS_SEC = 0x00000001,
NAMESPACE_SEC = 0x00000010,
COMPOUND_MASK = CLASS_SEC,
SCOPE_MASK = COMPOUND_MASK | NAMESPACE_SEC,
-
- CLASSDOC_SEC = 0x00000800,
+
+ CLASSDOC_SEC = 0x00000800,
STRUCTDOC_SEC = 0x00001000,
UNIONDOC_SEC = 0x00002000,
EXCEPTIONDOC_SEC = 0x00004000,
@@ -81,7 +81,7 @@ class Entry
CATEGORYDOC_SEC = 0x00040000,
SERVICEDOC_SEC = 0x00080000,
SINGLETONDOC_SEC = 0x00100000,
- COMPOUNDDOC_MASK = CLASSDOC_SEC | STRUCTDOC_SEC | UNIONDOC_SEC |
+ COMPOUNDDOC_MASK = CLASSDOC_SEC | STRUCTDOC_SEC | UNIONDOC_SEC |
INTERFACEDOC_SEC | EXCEPTIONDOC_SEC | PROTOCOLDOC_SEC |
CATEGORYDOC_SEC | SERVICEDOC_SEC | SINGLETONDOC_SEC,
@@ -134,7 +134,8 @@ class Entry
static const uint64 Enum = (1ULL<<12); // for Java-style enums
static const uint64 Service = (1ULL<<13); // UNO IDL
static const uint64 Singleton = (1ULL<<14); // UNO IDL
- static const uint64 ForwardDecl = (1ULL<<15); // forward declarad template classes
+ static const uint64 ForwardDecl = (1ULL<<15); // forward declared template classes
+ static const uint64 Local = (1ULL<<16); // for Slice types
// member specifiers (add new items to the beginning)
static const uint64 PrivateGettable = (1ULL<<20); // C# private getter
@@ -205,7 +206,7 @@ class Entry
/*! Returns the parent for this Entry or 0 if this entry has no parent. */
Entry *parent() const { return m_parent; }
- /*! Returns the list of children for this Entry
+ /*! Returns the list of children for this Entry
* @see addSubEntry() and removeSubEntry()
*/
const QList<Entry> *children() const { return m_sublist; }
@@ -213,14 +214,14 @@ class Entry
/*! Adds entry \a e as a child to this entry */
void addSubEntry (Entry* e) ;
- /*! Removes entry \a e from the list of children.
- * Returns a pointer to the entry or 0 if the entry was not a child.
+ /*! Removes entry \a e from the list of children.
+ * Returns a pointer to the entry or 0 if the entry was not a child.
* Note the entry will not be deleted.
- */
+ */
Entry *removeSubEntry(Entry *e);
/*! Restore the state of this Entry to the default value it has
- * at construction time.
+ * at construction time.
*/
void reset();
@@ -234,7 +235,7 @@ class Entry
// identification
int section; //!< entry type (see Sections);
- QCString type; //!< member type
+ QCString type; //!< member type
QCString name; //!< member name
TagInfo *tagInfo; //!< tag file info
@@ -242,14 +243,16 @@ class Entry
Protection protection; //!< class protection
MethodTypes mtype; //!< signal, slot, (dcop) method, or property?
uint64 spec; //!< class/member specifiers
- int initLines; //!< define/variable initializer lines to show
+ int initLines; //!< define/variable initializer lines to show
bool stat; //!< static ?
bool explicitExternal; //!< explicitly defined as external?
bool proto; //!< prototype ?
bool subGrouping; //!< automatically group class members?
bool callGraph; //!< do we need to draw the call graph?
bool callerGraph; //!< do we need to draw the caller graph?
- Specifier virt; //!< virtualness of the entry
+ bool referencedByRelation;//!< do we need to show the referenced by relation?
+ bool referencesRelation; //!< do we need to show the references relation?
+ Specifier virt; //!< virtualness of the entry
QCString args; //!< member argument string
QCString bitfields; //!< member's bit fields
ArgumentList *argList; //!< member arguments as a list
@@ -277,7 +280,7 @@ class Entry
int bodyLine; //!< line number of the definition in the source
int endBodyLine; //!< line number where the definition ends
int mGrpId; //!< member group id
- QList<BaseInfo> *extends; //!< list of base classes
+ QList<BaseInfo> *extends; //!< list of base classes
QList<Grouping> *groups; //!< list of groups this entry belongs to
QList<SectionInfo> *anchors; //!< list of anchors defined in this entry
QCString fileName; //!< file this entry was extracted from
@@ -290,6 +293,7 @@ class Entry
GroupDocType groupDocType;
QCString id; //!< libclang id
LocalToc localToc;
+ QCString metaData; //!< Slice metadata
static int num; //!< counts the total number of entries
@@ -297,7 +301,7 @@ class Entry
/// return the command name used to define GROUPDOC_SEC
const char *groupDocCmd() const
{
- switch( groupDocType )
+ switch( groupDocType )
{
case GROUPDOC_NORMAL: return "\\defgroup";
case GROUPDOC_ADD: return "\\addgroup";
@@ -307,11 +311,11 @@ class Entry
}
Grouping::GroupPri_t groupingPri() const
{
- if( section != GROUPDOC_SEC )
+ if( section != GROUPDOC_SEC )
{
return Grouping::GROUPING_LOWEST;
}
- switch( groupDocType )
+ switch( groupDocType )
{
case GROUPDOC_NORMAL: return Grouping::GROUPING_AUTO_DEF;
case GROUPDOC_ADD: return Grouping::GROUPING_AUTO_ADD;
@@ -320,11 +324,11 @@ class Entry
}
}
- private:
+ private:
void createSubtreeIndex(EntryNav *nav,FileStorage *storage,FileDef *fd);
Entry *m_parent; //!< parent node in the tree
QList<Entry> *m_sublist; //!< entries that are children of this one
- Entry &operator=(const Entry &);
+ Entry &operator=(const Entry &);
};
/** Wrapper for a node in the Entry tree.
@@ -357,13 +361,13 @@ class EntryNav
private:
- // navigation
+ // navigation
EntryNav *m_parent; //!< parent node in the tree
QList<EntryNav> *m_subList; //!< entries that are children of this one
// identification
int m_section; //!< entry type (see Sections);
- QCString m_type; //!< member type
+ QCString m_type; //!< member type
QCString m_name; //!< member name
TagInfo *m_tagInfo; //!< tag file info
FileDef *m_fileDef;
diff --git a/src/filedef.cpp b/src/filedef.cpp
index d9eaa4b..f9f68d1 100644
--- a/src/filedef.cpp
+++ b/src/filedef.cpp
@@ -85,6 +85,9 @@ FileDef::FileDef(const char *p,const char *nm,
setReference(lref);
setDiskName(dn?dn:nm);
m_classSDict = 0;
+ m_interfaceSDict = 0;
+ m_structSDict = 0;
+ m_exceptionSDict = 0;
m_includeList = 0;
m_includeDict = 0;
m_includedByList = 0;
@@ -112,6 +115,9 @@ FileDef::FileDef(const char *p,const char *nm,
FileDef::~FileDef()
{
delete m_classSDict;
+ delete m_interfaceSDict;
+ delete m_structSDict;
+ delete m_exceptionSDict;
delete m_includeDict;
delete m_includeList;
delete m_includedByDict;
@@ -239,18 +245,25 @@ void FileDef::writeTagFile(FTextStream &tagFile)
case LayoutDocEntry::FileClasses:
{
if (m_classSDict)
- {
- SDict<ClassDef>::Iterator ci(*m_classSDict);
- ClassDef *cd;
- for (ci.toFirst();(cd=ci.current());++ci)
- {
- if (cd->isLinkableInProject())
- {
- tagFile << " <class kind=\"" << cd->compoundTypeString() <<
- "\">" << convertToXML(cd->name()) << "</class>" << endl;
- }
- }
- }
+ writeClassesToTagFile(tagFile, m_classSDict);
+ }
+ break;
+ case LayoutDocEntry::FileInterfaces:
+ {
+ if (m_interfaceSDict)
+ writeClassesToTagFile(tagFile, m_interfaceSDict);
+ }
+ break;
+ case LayoutDocEntry::FileStructs:
+ {
+ if (m_structSDict)
+ writeClassesToTagFile(tagFile, m_structSDict);
+ }
+ break;
+ case LayoutDocEntry::FileExceptions:
+ {
+ if (m_exceptionSDict)
+ writeClassesToTagFile(tagFile, m_exceptionSDict);
}
break;
case LayoutDocEntry::FileNamespaces:
@@ -417,6 +430,20 @@ void FileDef::writeBriefDescription(OutputList &ol)
ol.writeSynopsis();
}
+void FileDef::writeClassesToTagFile(FTextStream &tagFile, ClassSDict *d)
+{
+ SDict<ClassDef>::Iterator ci(*d);
+ ClassDef *cd;
+ for (ci.toFirst();(cd=ci.current());++ci)
+ {
+ if (cd->isLinkableInProject())
+ {
+ tagFile << " <class kind=\"" << cd->compoundTypeString() <<
+ "\">" << convertToXML(cd->name()) << "</class>" << endl;
+ }
+ }
+}
+
void FileDef::writeIncludeFiles(OutputList &ol)
{
if (m_includeList && m_includeList->count()>0)
@@ -557,10 +584,10 @@ void FileDef::writeNamespaceDeclarations(OutputList &ol,const QCString &title,
if (m_namespaceSDict) m_namespaceSDict->writeDeclaration(ol,title,isConstantGroup);
}
-void FileDef::writeClassDeclarations(OutputList &ol,const QCString &title)
+void FileDef::writeClassDeclarations(OutputList &ol,const QCString &title,ClassSDict *d)
{
// write list of classes
- if (m_classSDict) m_classSDict->writeDeclaration(ol,0,title,FALSE);
+ if (d) d->writeDeclaration(ol,0,title,FALSE);
}
void FileDef::writeInlineClasses(OutputList &ol)
@@ -646,14 +673,38 @@ void FileDef::writeSummaryLinks(OutputList &ol)
SrcLangExt lang=getLanguage();
for (eli.toFirst();(lde=eli.current());++eli)
{
- if ((lde->kind()==LayoutDocEntry::FileClasses &&
- m_classSDict && m_classSDict->declVisible()) ||
- (lde->kind()==LayoutDocEntry::FileNamespaces &&
- m_namespaceSDict && m_namespaceSDict->declVisible())
- )
+ if (lde->kind()==LayoutDocEntry::FileClasses && m_classSDict && m_classSDict->declVisible())
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ QCString label = "nested-classes";
+ ol.writeSummaryLink(0,label,ls->title(lang),first);
+ first=FALSE;
+ }
+ else if (lde->kind()==LayoutDocEntry::FileInterfaces && m_interfaceSDict && m_interfaceSDict->declVisible())
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ QCString label = "interfaces";
+ ol.writeSummaryLink(0,label,ls->title(lang),first);
+ first=FALSE;
+ }
+ else if (lde->kind()==LayoutDocEntry::FileStructs && m_structSDict && m_structSDict->declVisible())
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ QCString label = "structs";
+ ol.writeSummaryLink(0,label,ls->title(lang),first);
+ first=FALSE;
+ }
+ else if (lde->kind()==LayoutDocEntry::FileExceptions && m_exceptionSDict && m_exceptionSDict->declVisible())
{
LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
- QCString label = lde->kind()==LayoutDocEntry::FileClasses ? "nested-classes" : "namespaces";
+ QCString label = "exceptions";
+ ol.writeSummaryLink(0,label,ls->title(lang),first);
+ first=FALSE;
+ }
+ else if (lde->kind()==LayoutDocEntry::FileNamespaces && m_namespaceSDict && m_namespaceSDict->declVisible())
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ QCString label = "namespaces";
ol.writeSummaryLink(0,label,ls->title(lang),first);
first=FALSE;
}
@@ -781,9 +832,27 @@ void FileDef::writeDocumentation(OutputList &ol)
case LayoutDocEntry::FileClasses:
{
LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
- writeClassDeclarations(ol,ls->title(lang));
+ writeClassDeclarations(ol,ls->title(lang),m_classSDict);
}
- break;
+ break;
+ case LayoutDocEntry::FileInterfaces:
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ writeClassDeclarations(ol,ls->title(lang),m_interfaceSDict);
+ }
+ break;
+ case LayoutDocEntry::FileStructs:
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ writeClassDeclarations(ol,ls->title(lang),m_structSDict);
+ }
+ break;
+ case LayoutDocEntry::FileExceptions:
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ writeClassDeclarations(ol,ls->title(lang),m_exceptionSDict);
+ }
+ break;
case LayoutDocEntry::FileNamespaces:
{
LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
@@ -842,6 +911,9 @@ void FileDef::writeDocumentation(OutputList &ol)
case LayoutDocEntry::NamespaceNestedNamespaces:
case LayoutDocEntry::NamespaceNestedConstantGroups:
case LayoutDocEntry::NamespaceClasses:
+ case LayoutDocEntry::NamespaceInterfaces:
+ case LayoutDocEntry::NamespaceStructs:
+ case LayoutDocEntry::NamespaceExceptions:
case LayoutDocEntry::NamespaceInlineClasses:
case LayoutDocEntry::GroupClasses:
case LayoutDocEntry::GroupInlineClasses:
@@ -1160,6 +1232,14 @@ void FileDef::insertMember(MemberDef *md)
addMemberToList(MemberListType_decTypedefMembers,md);
addMemberToList(MemberListType_docTypedefMembers,md);
break;
+ case MemberType_Sequence:
+ addMemberToList(MemberListType_decSequenceMembers,md);
+ addMemberToList(MemberListType_docSequenceMembers,md);
+ break;
+ case MemberType_Dictionary:
+ addMemberToList(MemberListType_decDictionaryMembers,md);
+ addMemberToList(MemberListType_docDictionaryMembers,md);
+ break;
case MemberType_Enumeration:
addMemberToList(MemberListType_decEnumMembers,md);
addMemberToList(MemberListType_docEnumMembers,md);
@@ -1184,17 +1264,36 @@ void FileDef::insertMember(MemberDef *md)
void FileDef::insertClass(ClassDef *cd)
{
if (cd->isHidden()) return;
- if (m_classSDict==0)
+
+ ClassSDict *d=0;
+ ClassSDict **dd=&m_classSDict;
+
+ if (Config_getBool(OPTIMIZE_OUTPUT_SLICE))
{
- m_classSDict = new ClassSDict(17);
+ if (cd->compoundType()==ClassDef::Interface)
+ {
+ dd = &m_interfaceSDict;
+ }
+ else if (cd->compoundType()==ClassDef::Struct)
+ {
+ dd = &m_structSDict;
+ }
+ else if (cd->compoundType()==ClassDef::Exception)
+ {
+ dd = &m_exceptionSDict;
+ }
}
+
+ if (*dd==0) *dd = new ClassSDict(17);
+ d = *dd;
+
if (Config_getBool(SORT_BRIEF_DOCS))
{
- m_classSDict->inSort(cd->name(),cd);
+ d->inSort(cd->name(),cd);
}
else
{
- m_classSDict->append(cd->name(),cd);
+ d->append(cd->name(),cd);
}
}
diff --git a/src/filedef.h b/src/filedef.h
index 9167249..fe3c81d 100644
--- a/src/filedef.h
+++ b/src/filedef.h
@@ -201,7 +201,7 @@ class FileDef : public Definition
void writeSourceLink(OutputList &ol);
void writeNamespaceDeclarations(OutputList &ol,const QCString &title,
bool isConstantGroup);
- void writeClassDeclarations(OutputList &ol,const QCString &title);
+ void writeClassDeclarations(OutputList &ol,const QCString &title,ClassSDict *d);
void writeInlineClasses(OutputList &ol);
void startMemberDeclarations(OutputList &ol);
void endMemberDeclarations(OutputList &ol);
@@ -209,6 +209,7 @@ class FileDef : public Definition
void endMemberDocumentation(OutputList &ol);
void writeDetailedDescription(OutputList &ol,const QCString &title);
void writeBriefDescription(OutputList &ol);
+ void writeClassesToTagFile(FTextStream &t,ClassSDict *d);
QDict<IncludeInfo> *m_includeDict;
QList<IncludeInfo> *m_includeList;
@@ -233,6 +234,9 @@ class FileDef : public Definition
MemberGroupSDict *m_memberGroupSDict;
NamespaceSDict *m_namespaceSDict;
ClassSDict *m_classSDict;
+ ClassSDict *m_interfaceSDict;
+ ClassSDict *m_structSDict;
+ ClassSDict *m_exceptionSDict;
bool m_subGrouping;
};
diff --git a/src/fortrancode.l b/src/fortrancode.l
index 3014dc3..0e610fd 100644
--- a/src/fortrancode.l
+++ b/src/fortrancode.l
@@ -107,8 +107,9 @@ class Scope
public:
QCStringList useNames; //!< contains names of used modules
QDict<void> localVars; //!< contains names of local variables
+ QDict<void> externalVars; //!< contains names of external entities
- Scope() : localVars(7, FALSE /*caseSensitive*/) {}
+ Scope() : localVars(7, FALSE /*caseSensitive*/), externalVars(7, FALSE /*caseSensitive*/) {}
};
/*===================================================================*/
@@ -122,6 +123,7 @@ static QCString currentClass=0; //!< name of the current enclosing
static UseSDict *useMembers= new UseSDict; //!< info about used modules
static UseEntry *useEntry = 0; //!< current use statement info
static QList<Scope> scopeStack;
+static bool g_isExternal = false;
// static QCStringList *currentUseNames= new QCStringList; //! contains names of used modules of current program unit
static QCString str=""; //!> contents of fortran string
@@ -434,7 +436,7 @@ static bool getFortranDefs(const QCString &memberName, const QCString &moduleNam
Scope *scope;
for (it.toLast();(scope=it.current());--it)
{
- if (scope->localVars.find(memberName))
+ if (scope->localVars.find(memberName) && (!scope->externalVars.find(memberName)))
return FALSE;
}
@@ -648,7 +650,10 @@ static void addUse(const QCString &moduleName)
static void addLocalVar(const QCString &varName)
{
if (!scopeStack.isEmpty())
+ {
scopeStack.getLast()->localVars.insert(varName, (void*)1);
+ if (g_isExternal) scopeStack.getLast()->externalVars.insert(varName, (void*)1);
+ }
}
//----------------------------------------------------------------------------
@@ -969,11 +974,18 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")
endFontClass();
}
<Start>{ATTR_SPEC} {
+ if (QCString(yytext) == "external")
+ {
+ yy_push_state(YY_START);
+ BEGIN(Declaration);
+ g_isExternal = true;
+ }
startFontClass("keywordtype");
g_code->codify(yytext);
endFontClass();
}
<Declaration>({TYPE_SPEC}|{ATTR_SPEC})/[,:( ] { //| variable declaration
+ if (QCString(yytext) == "external") g_isExternal = true;
startFontClass("keywordtype");
g_code->codify(yytext);
endFontClass();
@@ -1046,6 +1058,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")
g_contLineNr++;
if (!(g_hasContLine && g_hasContLine[g_contLineNr - 1]))
{
+ g_isExternal = false;
yy_pop_state();
}
YY_FTN_RESET
diff --git a/src/fortranscanner.l b/src/fortranscanner.l
index 884c86e..5f10669 100644
--- a/src/fortranscanner.l
+++ b/src/fortranscanner.l
@@ -231,6 +231,8 @@ static void updateVariablePrepassComment(int from, int to);
static void newLine();
static void initEntry();
+static const char *stateToString(int state);
+
//-----------------------------------------------------------------------------
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
@@ -1638,7 +1640,7 @@ const char* prepassFixedForm(const char* contents, int *hasContLine)
}
// fallthrough
default:
- if ((column < 6) && ((c - '0') >= 0) && ((c - '0') <= 9)) { // remove numbers, i.e. labels from first 5 positions.
+ if (!commented && (column < 6) && ((c - '0') >= 0) && ((c - '0') <= 9)) { // remove numbers, i.e. labels from first 5 positions.
newContents[j]=' ';
}
else if(column==6 && emptyLabel) { // continuation
@@ -2759,7 +2761,7 @@ void FortranLanguageScanner::parsePrototype(const char *text)
static void scanner_abort()
{
fprintf(stderr,"********************************************************************\n");
- fprintf(stderr,"Error in file %s line: %d, state: %d\n",yyFileName.data(),yyLineNr,YY_START);
+ fprintf(stderr,"Error in file %s line: %d, state: %d(%s)\n",yyFileName.data(),yyLineNr,YY_START,stateToString(YY_START));
fprintf(stderr,"********************************************************************\n");
EntryListIterator eli(*global_root->children());
@@ -2788,3 +2790,47 @@ extern "C" { // some bogus code to keep the compiler happy
}
#endif
+#define scanStateToString(x) case x: resultString = #x; break;
+static const char *stateToString(int state)
+{
+ const char *resultString;
+ switch(state)
+ {
+ scanStateToString(INITIAL)
+ scanStateToString(Subprog)
+ scanStateToString(SubprogPrefix)
+ scanStateToString(Parameterlist)
+ scanStateToString(SubprogBody)
+ scanStateToString(SubprogBodyContains)
+ scanStateToString(Start)
+ scanStateToString(Comment)
+ scanStateToString(Module)
+ scanStateToString(Program)
+ scanStateToString(ModuleBody)
+ scanStateToString(ModuleBodyContains)
+ scanStateToString(AttributeList)
+ scanStateToString(Variable)
+ scanStateToString(Initialization)
+ scanStateToString(ArrayInitializer)
+ scanStateToString(Enum)
+ scanStateToString(Typedef)
+ scanStateToString(TypedefBody)
+ scanStateToString(TypedefBodyContains)
+ scanStateToString(InterfaceBody)
+ scanStateToString(StrIgnore)
+ scanStateToString(String)
+ scanStateToString(Use)
+ scanStateToString(UseOnly)
+ scanStateToString(ModuleProcedure)
+ scanStateToString(Prepass)
+ scanStateToString(DocBlock)
+ scanStateToString(DocBackLine)
+ scanStateToString(EndDoc)
+ scanStateToString(BlockData)
+ scanStateToString(Prototype)
+ scanStateToString(PrototypeSubprog)
+ scanStateToString(PrototypeArgs)
+ default: resultString = "Unknown"; break;
+ }
+ return resultString;
+}
diff --git a/src/ftvhelp.cpp b/src/ftvhelp.cpp
index 8c46fd5..73ac775 100644
--- a/src/ftvhelp.cpp
+++ b/src/ftvhelp.cpp
@@ -35,6 +35,7 @@
#include "docparser.h"
#include "htmldocvisitor.h"
#include "filedef.h"
+#include "classdef.h"
#include "util.h"
#include "resourcemgr.h"
@@ -331,6 +332,27 @@ static void generateBriefDoc(FTextStream &t,Definition *def)
}
}
+static char compoundIcon(ClassDef *cd)
+{
+ char icon='C';
+ if (cd->getLanguage() == SrcLangExt_Slice)
+ {
+ if (cd->compoundType()==ClassDef::Interface)
+ {
+ icon='I';
+ }
+ else if (cd->compoundType()==ClassDef::Struct)
+ {
+ icon='S';
+ }
+ else if (cd->compoundType()==ClassDef::Exception)
+ {
+ icon='E';
+ }
+ }
+ return icon;
+}
+
void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,int maxLevel,int &index)
{
QListIterator<FTVNode> nli(nl);
@@ -359,11 +381,19 @@ void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,in
}
else if (n->def && n->def->definitionType()==Definition::TypeNamespace)
{
- t << "<span class=\"icona\"><span class=\"icon\">N</span></span>";
+ if (n->def->getLanguage() == SrcLangExt_Slice)
+ {
+ t << "<span class=\"icona\"><span class=\"icon\">M</span></span>";
+ }
+ else
+ {
+ t << "<span class=\"icona\"><span class=\"icon\">N</span></span>";
+ }
}
else if (n->def && n->def->definitionType()==Definition::TypeClass)
{
- t << "<span class=\"icona\"><span class=\"icon\">C</span></span>";
+ char icon=compoundIcon(dynamic_cast<ClassDef*>(n->def));
+ t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>";
}
else
{
@@ -407,11 +437,19 @@ void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,in
}
else if (n->def && n->def->definitionType()==Definition::TypeNamespace)
{
- t << "<span class=\"icona\"><span class=\"icon\">N</span></span>";
+ if (n->def->getLanguage() == SrcLangExt_Slice)
+ {
+ t << "<span class=\"icona\"><span class=\"icon\">M</span></span>";
+ }
+ else
+ {
+ t << "<span class=\"icona\"><span class=\"icon\">N</span></span>";
+ }
}
else if (n->def && n->def->definitionType()==Definition::TypeClass)
{
- t << "<span class=\"icona\"><span class=\"icon\">C</span></span>";
+ char icon=compoundIcon(dynamic_cast<ClassDef*>(n->def));
+ t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>";
}
else
{
diff --git a/src/groupdef.cpp b/src/groupdef.cpp
index ccfa0df..e918b1f 100644
--- a/src/groupdef.cpp
+++ b/src/groupdef.cpp
@@ -1220,8 +1220,14 @@ void GroupDef::writeDocumentation(OutputList &ol)
case LayoutDocEntry::NamespaceNestedNamespaces:
case LayoutDocEntry::NamespaceNestedConstantGroups:
case LayoutDocEntry::NamespaceClasses:
+ case LayoutDocEntry::NamespaceInterfaces:
+ case LayoutDocEntry::NamespaceStructs:
+ case LayoutDocEntry::NamespaceExceptions:
case LayoutDocEntry::NamespaceInlineClasses:
case LayoutDocEntry::FileClasses:
+ case LayoutDocEntry::FileInterfaces:
+ case LayoutDocEntry::FileStructs:
+ case LayoutDocEntry::FileExceptions:
case LayoutDocEntry::FileNamespaces:
case LayoutDocEntry::FileConstantGroups:
case LayoutDocEntry::FileIncludes:
diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp
index 6e0c62d..dfa6089 100644
--- a/src/htmldocvisitor.cpp
+++ b/src/htmldocvisitor.cpp
@@ -34,6 +34,7 @@
#include "filedef.h"
#include "memberdef.h"
#include "htmlentity.h"
+#include "emoji.h"
#include "plantuml.h"
static const int NUM_HTML_LIST_TYPES = 4;
@@ -151,7 +152,7 @@ static bool mustBeOutsideParagraph(DocNode *n)
return FALSE;
}
-static QString htmlAttribsToString(const HtmlAttribList &attribs, const bool img_tag = FALSE)
+static QString htmlAttribsToString(const HtmlAttribList &attribs, bool img_tag = FALSE)
{
QString result;
HtmlAttribListIterator li(attribs);
@@ -234,6 +235,20 @@ void HtmlDocVisitor::visit(DocSymbol *s)
}
}
+void HtmlDocVisitor::visit(DocEmoji *s)
+{
+ if (m_hide) return;
+ const char *res = EmojiEntityMapper::instance()->html(s->emoji());
+ if (res)
+ {
+ m_t << res;
+ }
+ else
+ {
+ err("HTML: non supported Emoji-entity found: %s\n",EmojiEntityMapper::instance()->html(s->emoji()));
+ }
+}
+
void HtmlDocVisitor::writeObfuscatedMailAddress(const QCString &url)
{
m_t << "<a href=\"#\" onclick=\"location.href='mai'+'lto:'";
@@ -388,7 +403,6 @@ static void visitCaption(HtmlDocVisitor *parent, QList<DocNode> children)
for (cli.toFirst();(n=cli.current());++cli) n->accept(parent);
}
-
void HtmlDocVisitor::visit(DocVerbatim *s)
{
if (m_hide) return;
@@ -428,10 +442,12 @@ void HtmlDocVisitor::visit(DocVerbatim *s)
m_t << "</pre>" /*<< PREFRAG_END*/;
forceStartParagraph(s);
break;
- case DocVerbatim::HtmlOnly:
- if (s->isBlock()) forceEndParagraph(s);
- m_t << s->text();
- if (s->isBlock()) forceStartParagraph(s);
+ case DocVerbatim::HtmlOnly:
+ {
+ if (s->isBlock()) forceEndParagraph(s);
+ m_t << s->text();
+ if (s->isBlock()) forceStartParagraph(s);
+ }
break;
case DocVerbatim::ManOnly:
case DocVerbatim::LatexOnly:
@@ -1532,7 +1548,22 @@ void HtmlDocVisitor::visitPre(DocImage *img)
{
if (img->type()==DocImage::Html)
{
- forceEndParagraph(img);
+ bool inlineImage = img->isInlineImage();
+ bool typeSVG = FALSE;
+
+ QCString url = img->url();
+ if (url.isEmpty())
+ {
+ typeSVG = (img->name().right(4)==".svg");
+ }
+ else
+ {
+ typeSVG = (url.right(4)==".svg");
+ }
+ if (!inlineImage && !typeSVG)
+ {
+ forceEndParagraph(img);
+ }
if (m_hide) return;
QString baseName=img->name();
int i;
@@ -1540,20 +1571,19 @@ void HtmlDocVisitor::visitPre(DocImage *img)
{
baseName=baseName.right(baseName.length()-i-1);
}
- m_t << "<div class=\"image\">" << endl;
- QCString url = img->url();
+ if (!inlineImage && !typeSVG) m_t << "<div class=\"image\">" << endl;
QCString sizeAttribs;
if (!img->width().isEmpty())
{
sizeAttribs+=" width=\""+img->width()+"\"";
}
- if (!img->height().isEmpty())
+ if (!img->height().isEmpty()) // link to local file
{
sizeAttribs+=" height=\""+img->height()+"\"";
}
if (url.isEmpty())
{
- if (img->name().right(4)==".svg")
+ if (typeSVG)
{
m_t << "<object type=\"image/svg+xml\" data=\"" << img->relPath() << img->name()
<< "\"" << sizeAttribs << htmlAttribsToString(img->attribs()) << ">" << baseName
@@ -1563,27 +1593,39 @@ void HtmlDocVisitor::visitPre(DocImage *img)
{
m_t << "<img src=\"" << img->relPath() << img->name() << "\" alt=\""
<< baseName << "\"" << sizeAttribs << htmlAttribsToString(img->attribs())
- << "/>" << endl;
+ << (inlineImage ? " class=\"inline\"" : "/>\n");
}
}
- else
+ else // link to URL
{
- if (url.right(4)==".svg")
+ if (typeSVG)
{
m_t << "<object type=\"image/svg+xml\" data=\"" << correctURL(url,img->relPath())
- << "\"" << sizeAttribs << htmlAttribsToString(img->attribs()) << "></object>" << endl;
+ << "\"" << sizeAttribs << htmlAttribsToString(img->attribs())
+ << "></object>" << endl;
}
else
{
m_t << "<img src=\"" << correctURL(url,img->relPath()) << "\""
<< sizeAttribs << htmlAttribsToString(img->attribs(), TRUE)
- << "/>" << endl;
+ << (inlineImage ? " class=\"inline\"" : "/>\n");
}
}
if (img->hasCaption())
{
- m_t << "<div class=\"caption\">" << endl;
- m_t << getHtmlDirEmbedingChar(getTextDirByConfig(img));
+ if (inlineImage)
+ {
+ m_t << " title=\"";
+ }
+ else
+ {
+ m_t << "<div class=\"caption\">" << endl;
+ m_t << getHtmlDirEmbedingChar(getTextDirByConfig(img));
+ }
+ }
+ else if (inlineImage)
+ {
+ m_t << "/>" << endl;
}
}
else // other format -> skip
@@ -1593,17 +1635,34 @@ void HtmlDocVisitor::visitPre(DocImage *img)
}
}
-void HtmlDocVisitor::visitPost(DocImage *img)
+void HtmlDocVisitor::visitPost(DocImage *img)
{
if (img->type()==DocImage::Html)
{
if (m_hide) return;
+ bool inlineImage = img->isInlineImage();
+ bool typeSVG = FALSE;
+ QCString url = img->url();
+ if (url.isEmpty())
+ {
+ typeSVG = (img->name().right(4)==".svg");
+ }
+ else
+ {
+ typeSVG = (url.right(4)==".svg");
+ }
if (img->hasCaption())
{
- m_t << "</div>";
+ if (inlineImage)
+ m_t << "\"/>\n ";
+ else
+ m_t << "</div>";
+ }
+ if (!inlineImage && !typeSVG)
+ {
+ m_t << "</div>" << endl;
+ forceStartParagraph(img);
}
- m_t << "</div>" << endl;
- forceStartParagraph(img);
}
else // other format
{
@@ -2218,6 +2277,30 @@ static bool insideStyleChangeThatIsOutsideParagraph(DocPara *para,int nodeIndex)
return styleOutsideParagraph;
}
+static bool isDocVerbatimVisible(DocVerbatim *s)
+{
+ switch(s->type())
+ {
+ case DocVerbatim::ManOnly:
+ case DocVerbatim::LatexOnly:
+ case DocVerbatim::XmlOnly:
+ case DocVerbatim::RtfOnly:
+ case DocVerbatim::DocbookOnly:
+ return FALSE;
+ default:
+ return TRUE;
+ }
+}
+
+static bool isInvisibleNode(DocNode *node)
+{
+ return (node->kind()==DocNode::Kind_WhiteSpace) ||
+ // skip over image nodes that are not for HTML output
+ (node->kind()==DocNode::Kind_Image && ((DocImage*)node)->type()!=DocImage::Html) ||
+ // skip over verbatim nodes that are not visible in the HTML output
+ (node->kind()==DocNode::Kind_Verbatim && !isDocVerbatimVisible((DocVerbatim*)node));
+}
+
/** Used for items found inside a paragraph, which due to XHTML restrictions
* have to be outside of the paragraph. This method will forcefully end
* the current paragraph and forceStartParagraph() will restart it.
@@ -2231,16 +2314,13 @@ void HtmlDocVisitor::forceEndParagraph(DocNode *n)
int nodeIndex = para->children().findRef(n);
nodeIndex--;
if (nodeIndex<0) return; // first node
- while (nodeIndex>=0 &&
- para->children().at(nodeIndex)->kind()==DocNode::Kind_WhiteSpace
- )
+ while (nodeIndex>=0 && isInvisibleNode(para->children().at(nodeIndex)))
{
- nodeIndex--;
+ nodeIndex--;
}
if (nodeIndex>=0)
{
DocNode *n = para->children().at(nodeIndex);
- //printf("n=%p kind=%d outside=%d\n",n,n->kind(),mustBeOutsideParagraph(n));
if (mustBeOutsideParagraph(n)) return;
}
nodeIndex--;
@@ -2272,16 +2352,14 @@ void HtmlDocVisitor::forceStartParagraph(DocNode *n)
if (styleOutsideParagraph) return;
nodeIndex++;
if (nodeIndex==numNodes) return; // last node
- while (nodeIndex<numNodes &&
- para->children().at(nodeIndex)->kind()==DocNode::Kind_WhiteSpace
- )
+ while (nodeIndex<numNodes && isInvisibleNode(para->children().at(nodeIndex)))
{
nodeIndex++;
}
if (nodeIndex<numNodes)
{
DocNode *n = para->children().at(nodeIndex);
- if (mustBeOutsideParagraph(n)) return;
+ if (mustBeOutsideParagraph(n)) return; // next element also outside paragraph
}
else
{
@@ -2292,8 +2370,8 @@ void HtmlDocVisitor::forceStartParagraph(DocNode *n)
bool isFirst;
bool isLast;
getParagraphContext(para,isFirst,isLast);
- //printf("forceStart first=%d last=%d\n",isFirst,isLast);
if (isFirst && isLast) needsTag = FALSE;
+ //printf("forceStart first=%d last=%d needsTag=%d\n",isFirst,isLast,needsTag);
if (needsTag)
m_t << "<p" << getDirHtmlClassOfNode(getTextDirByConfig(para, nodeIndex)) << ">";
diff --git a/src/htmldocvisitor.h b/src/htmldocvisitor.h
index 2ff9f75..7184f0f 100644
--- a/src/htmldocvisitor.h
+++ b/src/htmldocvisitor.h
@@ -43,6 +43,7 @@ class HtmlDocVisitor : public DocVisitor
void visit(DocLinkedWord *);
void visit(DocWhiteSpace *);
void visit(DocSymbol *);
+ void visit(DocEmoji *);
void visit(DocURL *);
void visit(DocLineBreak *);
void visit(DocHorRuler *);
diff --git a/src/htmlentity.cpp b/src/htmlentity.cpp
index 3d95705..e95b817 100644
--- a/src/htmlentity.cpp
+++ b/src/htmlentity.cpp
@@ -314,7 +314,8 @@ static struct htmlEntityInfo
{ SYM(Quot), "\"", "\"", "\"", "&quot;", "\"", "\"", "\"", { "\"", DocSymbol::Perl_char }},
{ SYM(Minus), "-", "-", "-", "-", "-\\/", "-", "-", { "-", DocSymbol::Perl_char }},
{ SYM(Plus), "+", "+", "+", "+", "+", "+", "+", { "+", DocSymbol::Perl_char }},
- { SYM(Dot), ".", ".", ".", ".", ".", ".", ".", { ".", DocSymbol::Perl_char }}
+ { SYM(Dot), ".", ".", ".", ".", ".", ".", ".", { ".", DocSymbol::Perl_char }},
+ { SYM(Colon), ":", ":", ":", ":", ":", ":", ":", { ":", DocSymbol::Perl_char }}
};
static const int g_numHtmlEntities = (int)(sizeof(g_htmlEntities)/ sizeof(*g_htmlEntities));
diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp
index 8819078..357c048 100644
--- a/src/htmlgen.cpp
+++ b/src/htmlgen.cpp
@@ -17,6 +17,7 @@
#include <stdlib.h>
+#include <assert.h>
#include <qdir.h>
#include <qregexp.h>
#include "message.h"
@@ -1396,6 +1397,7 @@ void HtmlGenerator::endClassDiagram(const ClassDiagram &d,
t << "_map\">" << endl;
d.writeImage(t,dir,relPath,fileName);
+ t << "<div/></map>" << endl;
t << " </div>";
endSectionContent(t);
m_sectionCount++;
@@ -2038,24 +2040,37 @@ static bool quickLinkVisible(LayoutNavEntry::Kind kind)
static bool showNamespaces = Config_getBool(SHOW_NAMESPACES);
switch (kind)
{
- case LayoutNavEntry::MainPage: return TRUE;
- case LayoutNavEntry::User: return TRUE;
- case LayoutNavEntry::UserGroup: return TRUE;
- case LayoutNavEntry::Pages: return indexedPages>0;
- case LayoutNavEntry::Modules: return documentedGroups>0;
- case LayoutNavEntry::Namespaces: return documentedNamespaces>0 && showNamespaces;
- case LayoutNavEntry::NamespaceList: return documentedNamespaces>0 && showNamespaces;
- case LayoutNavEntry::NamespaceMembers: return documentedNamespaceMembers[NMHL_All]>0;
- case LayoutNavEntry::Classes: return annotatedClasses>0;
- case LayoutNavEntry::ClassList: return annotatedClasses>0;
- case LayoutNavEntry::ClassIndex: return annotatedClasses>0;
- case LayoutNavEntry::ClassHierarchy: return hierarchyClasses>0;
- case LayoutNavEntry::ClassMembers: return documentedClassMembers[CMHL_All]>0;
- case LayoutNavEntry::Files: return documentedHtmlFiles>0 && showFiles;
- case LayoutNavEntry::FileList: return documentedHtmlFiles>0 && showFiles;
- case LayoutNavEntry::FileGlobals: return documentedFileMembers[FMHL_All]>0;
- //case LayoutNavEntry::Dirs: return documentedDirs>0;
- case LayoutNavEntry::Examples: return Doxygen::exampleSDict->count()>0;
+ case LayoutNavEntry::MainPage: return TRUE;
+ case LayoutNavEntry::User: return TRUE;
+ case LayoutNavEntry::UserGroup: return TRUE;
+ case LayoutNavEntry::Pages: return indexedPages>0;
+ case LayoutNavEntry::Modules: return documentedGroups>0;
+ case LayoutNavEntry::Namespaces: return documentedNamespaces>0 && showNamespaces;
+ case LayoutNavEntry::NamespaceList: return documentedNamespaces>0 && showNamespaces;
+ case LayoutNavEntry::NamespaceMembers: return documentedNamespaceMembers[NMHL_All]>0;
+ case LayoutNavEntry::Classes: return annotatedClasses>0;
+ case LayoutNavEntry::ClassList: return annotatedClasses>0;
+ case LayoutNavEntry::ClassIndex: return annotatedClasses>0;
+ case LayoutNavEntry::ClassHierarchy: return hierarchyClasses>0;
+ case LayoutNavEntry::ClassMembers: return documentedClassMembers[CMHL_All]>0;
+ case LayoutNavEntry::Files: return documentedHtmlFiles>0 && showFiles;
+ case LayoutNavEntry::FileList: return documentedHtmlFiles>0 && showFiles;
+ case LayoutNavEntry::FileGlobals: return documentedFileMembers[FMHL_All]>0;
+ case LayoutNavEntry::Examples: return Doxygen::exampleSDict->count()>0;
+ case LayoutNavEntry::Interfaces: return annotatedInterfaces>0;
+ case LayoutNavEntry::InterfaceList: return annotatedInterfaces>0;
+ case LayoutNavEntry::InterfaceIndex: return annotatedInterfaces>0;
+ case LayoutNavEntry::InterfaceHierarchy: return hierarchyInterfaces>0;
+ case LayoutNavEntry::Structs: return annotatedStructs>0;
+ case LayoutNavEntry::StructList: return annotatedStructs>0;
+ case LayoutNavEntry::StructIndex: return annotatedStructs>0;
+ case LayoutNavEntry::Exceptions: return annotatedExceptions>0;
+ case LayoutNavEntry::ExceptionList: return annotatedExceptions>0;
+ case LayoutNavEntry::ExceptionIndex: return annotatedExceptions>0;
+ case LayoutNavEntry::ExceptionHierarchy: return hierarchyExceptions>0;
+ case LayoutNavEntry::None: // should never happen, means not properly initialized
+ assert(kind != LayoutNavEntry::None);
+ return FALSE;
}
return FALSE;
}
@@ -2181,9 +2196,17 @@ static void writeDefaultQuickLinks(FTextStream &t,bool compact,
case HLI_Modules: kind = LayoutNavEntry::Modules; break;
//case HLI_Directories: kind = LayoutNavEntry::Dirs; break;
case HLI_Namespaces: kind = LayoutNavEntry::NamespaceList; altKind = LayoutNavEntry::Namespaces; break;
- case HLI_Hierarchy: kind = LayoutNavEntry::ClassHierarchy; break;
+ case HLI_ClassHierarchy: kind = LayoutNavEntry::ClassHierarchy; break;
+ case HLI_InterfaceHierarchy: kind = LayoutNavEntry::InterfaceHierarchy; break;
+ case HLI_ExceptionHierarchy: kind = LayoutNavEntry::ExceptionHierarchy; break;
case HLI_Classes: kind = LayoutNavEntry::ClassIndex; altKind = LayoutNavEntry::Classes; break;
- case HLI_Annotated: kind = LayoutNavEntry::ClassList; altKind = LayoutNavEntry::Classes; break;
+ case HLI_Interfaces: kind = LayoutNavEntry::InterfaceIndex; altKind = LayoutNavEntry::Interfaces; break;
+ case HLI_Structs: kind = LayoutNavEntry::StructIndex; altKind = LayoutNavEntry::Structs; break;
+ case HLI_Exceptions: kind = LayoutNavEntry::ExceptionIndex; altKind = LayoutNavEntry::Exceptions; break;
+ case HLI_AnnotatedClasses: kind = LayoutNavEntry::ClassList; altKind = LayoutNavEntry::Classes; break;
+ case HLI_AnnotatedInterfaces: kind = LayoutNavEntry::InterfaceList; altKind = LayoutNavEntry::Interfaces; break;
+ case HLI_AnnotatedStructs: kind = LayoutNavEntry::StructList; altKind = LayoutNavEntry::Structs; break;
+ case HLI_AnnotatedExceptions: kind = LayoutNavEntry::ExceptionList; altKind = LayoutNavEntry::Exceptions; break;
case HLI_Files: kind = LayoutNavEntry::FileList; altKind = LayoutNavEntry::Files; break;
case HLI_NamespaceMembers: kind = LayoutNavEntry::NamespaceMembers; break;
case HLI_Functions: kind = LayoutNavEntry::ClassMembers; break;
@@ -2193,6 +2216,12 @@ static void writeDefaultQuickLinks(FTextStream &t,bool compact,
case HLI_UserGroup: kind = LayoutNavEntry::UserGroup; break;
case HLI_ClassVisible: kind = LayoutNavEntry::ClassList; altKind = LayoutNavEntry::Classes;
highlightParent = TRUE; break;
+ case HLI_InterfaceVisible: kind = LayoutNavEntry::InterfaceList; altKind = LayoutNavEntry::Interfaces;
+ highlightParent = TRUE; break;
+ case HLI_StructVisible: kind = LayoutNavEntry::StructList; altKind = LayoutNavEntry::Structs;
+ highlightParent = TRUE; break;
+ case HLI_ExceptionVisible: kind = LayoutNavEntry::ExceptionList; altKind = LayoutNavEntry::Exceptions;
+ highlightParent = TRUE; break;
case HLI_NamespaceVisible: kind = LayoutNavEntry::NamespaceList; altKind = LayoutNavEntry::Namespaces;
highlightParent = TRUE; break;
case HLI_FileVisible: kind = LayoutNavEntry::FileList; altKind = LayoutNavEntry::Files;
diff --git a/src/index.cpp b/src/index.cpp
index 503387c..84b5e51 100644
--- a/src/index.cpp
+++ b/src/index.cpp
@@ -21,6 +21,7 @@
#include <stdlib.h>
+#include <assert.h>
#include <qtextstream.h>
#include <qdatetime.h>
#include <qdir.h>
@@ -55,6 +56,14 @@
int annotatedClasses;
int annotatedClassesPrinted;
int hierarchyClasses;
+int annotatedInterfaces;
+int annotatedInterfacesPrinted;
+int hierarchyInterfaces;
+int annotatedStructs;
+int annotatedStructsPrinted;
+int annotatedExceptions;
+int annotatedExceptionsPrinted;
+int hierarchyExceptions;
int documentedFiles;
int documentedGroups;
int documentedNamespaces;
@@ -66,23 +75,34 @@ int documentedHtmlFiles;
int documentedPages;
int documentedDirs;
-static int countClassHierarchy();
+static int countClassHierarchy(ClassDef::CompoundType ct);
static void countFiles(int &htmlFiles,int &files);
static int countGroups();
static int countDirs();
static int countNamespaces();
-static int countAnnotatedClasses(int *cp);
+static int countAnnotatedClasses(int *cp,ClassDef::CompoundType ct);
static void countRelatedPages(int &docPages,int &indexPages);
void countDataStructures()
{
- annotatedClasses = countAnnotatedClasses(&annotatedClassesPrinted); // "classes" + "annotated"
- hierarchyClasses = countClassHierarchy(); // "hierarchy"
- countFiles(documentedHtmlFiles,documentedFiles); // "files"
- countRelatedPages(documentedPages,indexedPages); // "pages"
- documentedGroups = countGroups(); // "modules"
- documentedNamespaces = countNamespaces(); // "namespaces"
- documentedDirs = countDirs(); // "dirs"
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+ annotatedClasses = countAnnotatedClasses(&annotatedClassesPrinted, ClassDef::Class); // "classes" + "annotated"
+ hierarchyClasses = countClassHierarchy(ClassDef::Class); // "hierarchy"
+ // "interfaces" + "annotated"
+ annotatedInterfaces = sliceOpt ? countAnnotatedClasses(&annotatedInterfacesPrinted, ClassDef::Interface) : 0;
+ // "interfacehierarchy"
+ hierarchyInterfaces = sliceOpt ? countClassHierarchy(ClassDef::Interface) : 0;
+ // "structs" + "annotated"
+ annotatedStructs = sliceOpt ? countAnnotatedClasses(&annotatedStructsPrinted, ClassDef::Struct) : 0;
+ // "exceptions" + "annotated"
+ annotatedExceptions = sliceOpt ? countAnnotatedClasses(&annotatedExceptionsPrinted, ClassDef::Exception) : 0;
+ // "exceptionhierarchy"
+ hierarchyExceptions = sliceOpt ? countClassHierarchy(ClassDef::Exception) : 0;
+ countFiles(documentedHtmlFiles,documentedFiles); // "files"
+ countRelatedPages(documentedPages,indexedPages); // "pages"
+ documentedGroups = countGroups(); // "modules"
+ documentedNamespaces = countNamespaces(); // "namespaces"
+ documentedDirs = countDirs(); // "dirs"
// "globals"
// "namespacemembers"
// "functions"
@@ -804,8 +824,10 @@ static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex)
//----------------------------------------------------------------------------
-static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FTVHelp* ftv,bool addToIndex)
+static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FTVHelp* ftv,bool addToIndex,
+ ClassDef::CompoundType ct)
{
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
ClassSDict::Iterator cli(*cl);
ClassDef *cd;
for (;(cd=cli.current());++cli)
@@ -824,6 +846,10 @@ static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FT
}
b=!hasVisibleRoot(cd->subClasses());
}
+ else if (sliceOpt && cd->compoundType() != ct)
+ {
+ continue;
+ }
else
{
b=!hasVisibleRoot(cd->baseClasses());
@@ -898,7 +924,7 @@ static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FT
}
}
-static void writeClassHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex)
+static void writeClassHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex,ClassDef::CompoundType ct)
{
initClassHierarchy(Doxygen::classSDict);
initClassHierarchy(Doxygen::hiddenClasses);
@@ -908,8 +934,8 @@ static void writeClassHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex)
ol.disable(OutputGenerator::Html);
}
bool started=FALSE;
- writeClassTreeForList(ol,Doxygen::classSDict,started,ftv,addToIndex);
- writeClassTreeForList(ol,Doxygen::hiddenClasses,started,ftv,addToIndex);
+ writeClassTreeForList(ol,Doxygen::classSDict,started,ftv,addToIndex,ct);
+ writeClassTreeForList(ol,Doxygen::hiddenClasses,started,ftv,addToIndex,ct);
if (started)
{
endIndexHierarchy(ol,0);
@@ -926,13 +952,18 @@ static void writeClassHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex)
//----------------------------------------------------------------------------
-static int countClassesInTreeList(const ClassSDict &cl)
+static int countClassesInTreeList(const ClassSDict &cl, ClassDef::CompoundType ct)
{
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
int count=0;
ClassSDict::Iterator cli(cl);
ClassDef *cd;
for (;(cd=cli.current());++cli)
{
+ if (sliceOpt && cd->compoundType() != ct)
+ {
+ continue;
+ }
if (!hasVisibleRoot(cd->baseClasses())) // filter on root classes
{
if (cd->isVisibleInHierarchy()) // should it be visible
@@ -947,13 +978,13 @@ static int countClassesInTreeList(const ClassSDict &cl)
return count;
}
-static int countClassHierarchy()
+static int countClassHierarchy(ClassDef::CompoundType ct)
{
int count=0;
initClassHierarchy(Doxygen::classSDict);
initClassHierarchy(Doxygen::hiddenClasses);
- count+=countClassesInTreeList(*Doxygen::classSDict);
- count+=countClassesInTreeList(*Doxygen::hiddenClasses);
+ count+=countClassesInTreeList(*Doxygen::classSDict, ct);
+ count+=countClassesInTreeList(*Doxygen::hiddenClasses, ct);
return count;
}
@@ -971,7 +1002,7 @@ static void writeHierarchicalIndex(OutputList &ol)
QCString title = lne ? lne->title() : theTranslator->trClassHierarchy();
bool addToIndex = lne==0 || lne->visible();
- startFile(ol,"hierarchy",0, title, HLI_Hierarchy);
+ startFile(ol,"hierarchy",0, title, HLI_ClassHierarchy);
startTitle(ol,0);
ol.parseText(title);
endTitle(ol,0,0);
@@ -1002,7 +1033,7 @@ static void writeHierarchicalIndex(OutputList &ol)
ol.disable(OutputGenerator::Html);
Doxygen::indexList->disable();
- writeClassHierarchy(ol,0,addToIndex);
+ writeClassHierarchy(ol,0,addToIndex,ClassDef::Class);
Doxygen::indexList->enable();
ol.popGeneratorState();
@@ -1021,7 +1052,7 @@ static void writeHierarchicalIndex(OutputList &ol)
Doxygen::indexList->addContentsItem(TRUE,title,0,"hierarchy",0,TRUE,TRUE);
}
FTVHelp* ftv = new FTVHelp(FALSE);
- writeClassHierarchy(ol,ftv,addToIndex);
+ writeClassHierarchy(ol,ftv,addToIndex,ClassDef::Class);
QGString outStr;
FTextStream t(&outStr);
ftv->generateTreeViewInline(t);
@@ -1048,7 +1079,7 @@ static void writeGraphicalClassHierarchy(OutputList &ol)
ol.disableAllBut(OutputGenerator::Html);
LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassHierarchy);
QCString title = lne ? lne->title() : theTranslator->trClassHierarchy();
- startFile(ol,"inherits",0,title,HLI_Hierarchy,FALSE,"hierarchy");
+ startFile(ol,"inherits",0,title,HLI_ClassHierarchy,FALSE,"hierarchy");
startTitle(ol,0);
ol.parseText(title);
endTitle(ol,0,0);
@@ -1068,6 +1099,220 @@ static void writeGraphicalClassHierarchy(OutputList &ol)
//----------------------------------------------------------------------------
+static void writeHierarchicalInterfaceIndex(OutputList &ol)
+{
+ if (hierarchyInterfaces==0) return;
+ ol.pushGeneratorState();
+ //1.{
+ ol.disable(OutputGenerator::Man);
+
+ LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::InterfaceHierarchy);
+ QCString title = lne ? lne->title() : theTranslator->trInterfaceHierarchy();
+ bool addToIndex = lne==0 || lne->visible();
+
+ startFile(ol,"interfacehierarchy",0, title, HLI_InterfaceHierarchy);
+ startTitle(ol,0);
+ ol.parseText(title);
+ endTitle(ol,0,0);
+ ol.startContents();
+ ol.startTextBlock();
+
+ if (Config_getBool(HAVE_DOT) && Config_getBool(GRAPHICAL_HIERARCHY))
+ {
+ ol.disable(OutputGenerator::Latex);
+ ol.disable(OutputGenerator::RTF);
+ ol.startParagraph();
+ ol.startTextLink("interfaceinherits",0);
+ ol.parseText(theTranslator->trGotoGraphicalHierarchy());
+ ol.endTextLink();
+ ol.endParagraph();
+ ol.enable(OutputGenerator::Latex);
+ ol.enable(OutputGenerator::RTF);
+ }
+ ol.parseText(lne ? lne->intro() : theTranslator->trInterfaceHierarchyDescription());
+ ol.endTextBlock();
+
+ // ---------------
+ // Static interface hierarchy for Latex/RTF
+ // ---------------
+ ol.pushGeneratorState();
+ //2.{
+ ol.disable(OutputGenerator::Html);
+ Doxygen::indexList->disable();
+
+ writeClassHierarchy(ol,0,addToIndex,ClassDef::Interface);
+
+ Doxygen::indexList->enable();
+ ol.popGeneratorState();
+ //2.}
+
+ // ---------------
+ // Dynamic interface hierarchical index for HTML
+ // ---------------
+ ol.pushGeneratorState();
+ //2.{
+ ol.disableAllBut(OutputGenerator::Html);
+
+ {
+ if (addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(TRUE,title,0,"interfacehierarchy",0,TRUE,TRUE);
+ }
+ FTVHelp* ftv = new FTVHelp(FALSE);
+ writeClassHierarchy(ol,ftv,addToIndex,ClassDef::Interface);
+ QGString outStr;
+ FTextStream t(&outStr);
+ ftv->generateTreeViewInline(t);
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.writeString(outStr);
+ ol.popGeneratorState();
+ delete ftv;
+ }
+ ol.popGeneratorState();
+ //2.}
+ // ------
+
+ endFile(ol);
+ ol.popGeneratorState();
+ //1.}
+}
+
+//----------------------------------------------------------------------------
+
+static void writeGraphicalInterfaceHierarchy(OutputList &ol)
+{
+ if (hierarchyInterfaces==0) return;
+ ol.disableAllBut(OutputGenerator::Html);
+ LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::InterfaceHierarchy);
+ QCString title = lne ? lne->title() : theTranslator->trInterfaceHierarchy();
+ startFile(ol,"interfaceinherits",0,title,HLI_InterfaceHierarchy,FALSE,"interfacehierarchy");
+ startTitle(ol,0);
+ ol.parseText(title);
+ endTitle(ol,0,0);
+ ol.startContents();
+ ol.startTextBlock();
+ ol.startParagraph();
+ ol.startTextLink("interfacehierarchy",0);
+ ol.parseText(theTranslator->trGotoTextualHierarchy());
+ ol.endTextLink();
+ ol.endParagraph();
+ ol.endTextBlock();
+ DotGfxHierarchyTable g("interface_",ClassDef::Interface);
+ ol.writeGraphicalHierarchy(g);
+ endFile(ol);
+ ol.enableAll();
+}
+
+//----------------------------------------------------------------------------
+
+static void writeHierarchicalExceptionIndex(OutputList &ol)
+{
+ if (hierarchyExceptions==0) return;
+ ol.pushGeneratorState();
+ //1.{
+ ol.disable(OutputGenerator::Man);
+
+ LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ExceptionHierarchy);
+ QCString title = lne ? lne->title() : theTranslator->trExceptionHierarchy();
+ bool addToIndex = lne==0 || lne->visible();
+
+ startFile(ol,"exceptionhierarchy",0, title, HLI_ExceptionHierarchy);
+ startTitle(ol,0);
+ ol.parseText(title);
+ endTitle(ol,0,0);
+ ol.startContents();
+ ol.startTextBlock();
+
+ if (Config_getBool(HAVE_DOT) && Config_getBool(GRAPHICAL_HIERARCHY))
+ {
+ ol.disable(OutputGenerator::Latex);
+ ol.disable(OutputGenerator::RTF);
+ ol.startParagraph();
+ ol.startTextLink("exceptioninherits",0);
+ ol.parseText(theTranslator->trGotoGraphicalHierarchy());
+ ol.endTextLink();
+ ol.endParagraph();
+ ol.enable(OutputGenerator::Latex);
+ ol.enable(OutputGenerator::RTF);
+ }
+ ol.parseText(lne ? lne->intro() : theTranslator->trExceptionHierarchyDescription());
+ ol.endTextBlock();
+
+ // ---------------
+ // Static exception hierarchy for Latex/RTF
+ // ---------------
+ ol.pushGeneratorState();
+ //2.{
+ ol.disable(OutputGenerator::Html);
+ Doxygen::indexList->disable();
+
+ writeClassHierarchy(ol,0,addToIndex,ClassDef::Exception);
+
+ Doxygen::indexList->enable();
+ ol.popGeneratorState();
+ //2.}
+
+ // ---------------
+ // Dynamic exception hierarchical index for HTML
+ // ---------------
+ ol.pushGeneratorState();
+ //2.{
+ ol.disableAllBut(OutputGenerator::Html);
+
+ {
+ if (addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(TRUE,title,0,"exceptionhierarchy",0,TRUE,TRUE);
+ }
+ FTVHelp* ftv = new FTVHelp(FALSE);
+ writeClassHierarchy(ol,ftv,addToIndex,ClassDef::Exception);
+ QGString outStr;
+ FTextStream t(&outStr);
+ ftv->generateTreeViewInline(t);
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.writeString(outStr);
+ ol.popGeneratorState();
+ delete ftv;
+ }
+ ol.popGeneratorState();
+ //2.}
+ // ------
+
+ endFile(ol);
+ ol.popGeneratorState();
+ //1.}
+}
+
+//----------------------------------------------------------------------------
+
+static void writeGraphicalExceptionHierarchy(OutputList &ol)
+{
+ if (hierarchyExceptions==0) return;
+ ol.disableAllBut(OutputGenerator::Html);
+ LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ExceptionHierarchy);
+ QCString title = lne ? lne->title() : theTranslator->trExceptionHierarchy();
+ startFile(ol,"exceptioninherits",0,title,HLI_ExceptionHierarchy,FALSE,"exceptionhierarchy");
+ startTitle(ol,0);
+ ol.parseText(title);
+ endTitle(ol,0,0);
+ ol.startContents();
+ ol.startTextBlock();
+ ol.startParagraph();
+ ol.startTextLink("exceptionhierarchy",0);
+ ol.parseText(theTranslator->trGotoTextualHierarchy());
+ ol.endTextLink();
+ ol.endParagraph();
+ ol.endTextBlock();
+ DotGfxHierarchyTable g("exception_",ClassDef::Exception);
+ ol.writeGraphicalHierarchy(g);
+ endFile(ol);
+ ol.enableAll();
+}
+
+//----------------------------------------------------------------------------
+
static void countFiles(int &htmlFiles,int &files)
{
htmlFiles=0;
@@ -1326,8 +1571,9 @@ static int countNamespaces()
//----------------------------------------------------------------------------
-void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalOnly)
+void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalOnly,ClassDef::CompoundType ct)
{
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
if (clDict)
{
ClassSDict::Iterator cli(*clDict);
@@ -1349,6 +1595,11 @@ void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalO
}
}
+ if (sliceOpt && cd->compoundType() != ct)
+ {
+ continue;
+ }
+
if (!globalOnly ||
cd->getOuterScope()==0 ||
cd->getOuterScope()==Doxygen::globalScope
@@ -1386,7 +1637,7 @@ void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalO
if (count>0)
{
ftv->incContentsDepth();
- writeClassTree(cd->getClassSDict(),ftv,addToIndex,FALSE);
+ writeClassTree(cd->getClassSDict(),ftv,addToIndex,FALSE,ct);
ftv->decContentsDepth();
}
}
@@ -1396,8 +1647,9 @@ void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalO
}
static void writeNamespaceTree(NamespaceSDict *nsDict,FTVHelp *ftv,
- bool rootOnly,bool showClasses,bool addToIndex)
+ bool rootOnly,bool showClasses,bool addToIndex,ClassDef::CompoundType ct)
{
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
if (nsDict)
{
NamespaceSDict::Iterator nli(*nsDict);
@@ -1408,7 +1660,7 @@ static void writeNamespaceTree(NamespaceSDict *nsDict,FTVHelp *ftv,
(!rootOnly || nd->getOuterScope()==Doxygen::globalScope))
{
- bool hasChildren = namespaceHasVisibleChild(nd,showClasses);
+ bool hasChildren = namespaceHasVisibleChild(nd,showClasses,sliceOpt,ct);
bool isLinkable = nd->isLinkableInProject();
QCString ref;
@@ -1439,10 +1691,26 @@ static void writeNamespaceTree(NamespaceSDict *nsDict,FTVHelp *ftv,
{
if (addToIndex) Doxygen::indexList->incContentsDepth();
ftv->incContentsDepth();
- writeNamespaceTree(nd->getNamespaceSDict(),ftv,FALSE,showClasses,addToIndex);
+ writeNamespaceTree(nd->getNamespaceSDict(),ftv,FALSE,showClasses,addToIndex,ct);
if (showClasses)
{
- writeClassTree(nd->getClassSDict(),ftv,addToIndex,FALSE);
+ ClassSDict *d = nd->getClassSDict();
+ if (sliceOpt)
+ {
+ if (ct == ClassDef::Interface)
+ {
+ d = nd->getInterfaceSDict();
+ }
+ else if (ct == ClassDef::Struct)
+ {
+ d = nd->getStructSDict();
+ }
+ else if (ct == ClassDef::Exception)
+ {
+ d = nd->getExceptionSDict();
+ }
+ }
+ writeClassTree(d,ftv,addToIndex,FALSE,ct);
}
ftv->decContentsDepth();
if (addToIndex) Doxygen::indexList->decContentsDepth();
@@ -1542,7 +1810,7 @@ static void writeNamespaceIndex(OutputList &ol)
Doxygen::indexList->incContentsDepth();
}
FTVHelp* ftv = new FTVHelp(FALSE);
- writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,FALSE,addToIndex);
+ writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,FALSE,addToIndex,ClassDef::Class);
QGString outStr;
FTextStream t(&outStr);
ftv->generateTreeViewInline(t);
@@ -1563,14 +1831,19 @@ static void writeNamespaceIndex(OutputList &ol)
//----------------------------------------------------------------------------
-static int countAnnotatedClasses(int *cp)
+static int countAnnotatedClasses(int *cp, ClassDef::CompoundType ct)
{
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
int count=0;
int countPrinted=0;
ClassSDict::Iterator cli(*Doxygen::classSDict);
ClassDef *cd;
for (;(cd=cli.current());++cli)
{
+ if (sliceOpt && cd->compoundType() != ct)
+ {
+ continue;
+ }
if (cd->isLinkableInProject() && cd->templateMaster()==0)
{
if (!cd->isEmbeddedInOuterScope())
@@ -1585,12 +1858,14 @@ static int countAnnotatedClasses(int *cp)
}
-static void writeAnnotatedClassList(OutputList &ol)
+static void writeAnnotatedClassList(OutputList &ol,ClassDef::CompoundType ct)
{
//LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassList);
//bool addToIndex = lne==0 || lne->visible();
bool first=TRUE;
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+
ClassSDict::Iterator cli(*Doxygen::classSDict);
ClassDef *cd;
@@ -1609,6 +1884,11 @@ static void writeAnnotatedClassList(OutputList &ol)
first=FALSE;
}
+ if (sliceOpt && cd->compoundType() != ct)
+ {
+ continue;
+ }
+
ol.pushGeneratorState();
if (cd->isEmbeddedInOuterScope())
{
@@ -1779,8 +2059,10 @@ class UsedIndexLetters : public SIntDict<uint>
};
// write an alphabetical index of all class with a header for each letter
-static void writeAlphabeticalClassList(OutputList &ol)
+static void writeAlphabeticalClassList(OutputList &ol, ClassDef::CompoundType ct, int annotatedCount)
{
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+
// What starting letters are used
UsedIndexLetters indexLettersUsed;
@@ -1791,6 +2073,8 @@ static void writeAlphabeticalClassList(OutputList &ol)
int headerItems=0;
for (;(cd=cli.current());++cli)
{
+ if (sliceOpt && cd->compoundType() != ct)
+ continue;
if (cd->isLinkableInProject() && cd->templateMaster()==0)
{
if (cd->getLanguage()==SrcLangExt_VHDL && !((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ENTITYCLASS ))// no architecture
@@ -1826,7 +2110,7 @@ static void writeAlphabeticalClassList(OutputList &ol)
const int columns = Config_getInt(COLS_IN_ALPHA_INDEX);
int i,j;
- int totalItems = headerItems*2 + annotatedClasses; // number of items in the table (headers span 2 items)
+ int totalItems = headerItems*2 + annotatedCount; // number of items in the table (headers span 2 items)
int rows = (totalItems + columns - 1)/columns; // number of rows in the table
//printf("headerItems=%d totalItems=%d columns=%d rows=%d itemsInLastRow=%d\n",
@@ -1843,6 +2127,8 @@ static void writeAlphabeticalClassList(OutputList &ol)
startLetter=0;
for (cli.toFirst();(cd=cli.current());++cli)
{
+ if (sliceOpt && cd->compoundType() != ct)
+ continue;
if (cd->getLanguage()==SrcLangExt_VHDL && !((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ENTITYCLASS ))// no architecture
continue;
@@ -2032,7 +2318,6 @@ static void writeAlphabeticalIndex(OutputList &ol)
if (annotatedClasses==0) return;
ol.pushGeneratorState();
ol.disableAllBut(OutputGenerator::Html);
- ol.disable(OutputGenerator::Docbook);
LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassIndex);
QCString title = lne ? lne->title() : theTranslator->trCompoundIndex();
bool addToIndex = lne==0 || lne->visible();
@@ -2049,7 +2334,94 @@ static void writeAlphabeticalIndex(OutputList &ol)
}
ol.startContents();
- writeAlphabeticalClassList(ol);
+ writeAlphabeticalClassList(ol, ClassDef::Class, annotatedClasses);
+ endFile(ol); // contains ol.endContents()
+
+ ol.popGeneratorState();
+}
+
+//----------------------------------------------------------------------------
+
+static void writeAlphabeticalInterfaceIndex(OutputList &ol)
+{
+ if (annotatedInterfaces==0) return;
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Html);
+ LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::InterfaceIndex);
+ QCString title = lne ? lne->title() : theTranslator->trInterfaceIndex();
+ bool addToIndex = lne==0 || lne->visible();
+
+ startFile(ol,"interfaces",0,title,HLI_Interfaces);
+
+ startTitle(ol,0);
+ ol.parseText(title);
+ endTitle(ol,0,0);
+
+ if (addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(FALSE,title,0,"interfaces",0,FALSE,TRUE);
+ }
+
+ ol.startContents();
+ writeAlphabeticalClassList(ol, ClassDef::Interface, annotatedInterfaces);
+ endFile(ol); // contains ol.endContents()
+
+ ol.popGeneratorState();
+}
+
+//----------------------------------------------------------------------------
+
+static void writeAlphabeticalStructIndex(OutputList &ol)
+{
+ if (annotatedStructs==0) return;
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Html);
+ LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::StructIndex);
+ QCString title = lne ? lne->title() : theTranslator->trStructIndex();
+ bool addToIndex = lne==0 || lne->visible();
+
+ startFile(ol,"structs",0,title,HLI_Structs);
+
+ startTitle(ol,0);
+ ol.parseText(title);
+ endTitle(ol,0,0);
+
+ if (addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(FALSE,title,0,"structs",0,FALSE,TRUE);
+ }
+
+ ol.startContents();
+ writeAlphabeticalClassList(ol, ClassDef::Struct, annotatedStructs);
+ endFile(ol); // contains ol.endContents()
+
+ ol.popGeneratorState();
+}
+
+//----------------------------------------------------------------------------
+
+static void writeAlphabeticalExceptionIndex(OutputList &ol)
+{
+ if (annotatedExceptions==0) return;
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Html);
+ LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ExceptionIndex);
+ QCString title = lne ? lne->title() : theTranslator->trExceptionIndex();
+ bool addToIndex = lne==0 || lne->visible();
+
+ startFile(ol,"exceptions",0,title,HLI_Exceptions);
+
+ startTitle(ol,0);
+ ol.parseText(title);
+ endTitle(ol,0,0);
+
+ if (addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(FALSE,title,0,"exceptions",0,FALSE,TRUE);
+ }
+
+ ol.startContents();
+ writeAlphabeticalClassList(ol, ClassDef::Exception, annotatedExceptions);
endFile(ol); // contains ol.endContents()
ol.popGeneratorState();
@@ -2065,7 +2437,6 @@ static void writeAnnotatedIndex(OutputList &ol)
ol.pushGeneratorState();
ol.disable(OutputGenerator::Man);
- ol.disable(OutputGenerator::Docbook);
if (annotatedClassesPrinted==0)
{
ol.disable(OutputGenerator::Latex);
@@ -2077,7 +2448,7 @@ static void writeAnnotatedIndex(OutputList &ol)
bool addToIndex = lne==0 || lne->visible();
- startFile(ol,"annotated",0,title,HLI_Annotated);
+ startFile(ol,"annotated",0,title,HLI_AnnotatedClasses);
startTitle(ol,0);
ol.parseText(title);
@@ -2096,7 +2467,7 @@ static void writeAnnotatedIndex(OutputList &ol)
ol.disable(OutputGenerator::Html);
Doxygen::indexList->disable();
- writeAnnotatedClassList(ol);
+ writeAnnotatedClassList(ol, ClassDef::Class);
Doxygen::indexList->enable();
ol.popGeneratorState();
@@ -2114,8 +2485,239 @@ static void writeAnnotatedIndex(OutputList &ol)
Doxygen::indexList->incContentsDepth();
}
FTVHelp* ftv = new FTVHelp(FALSE);
- writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex);
- writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE);
+ writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex,ClassDef::Class);
+ writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE,ClassDef::Class);
+ QGString outStr;
+ FTextStream t(&outStr);
+ ftv->generateTreeViewInline(t);
+ ol.writeString(outStr);
+ delete ftv;
+ if (addToIndex)
+ {
+ Doxygen::indexList->decContentsDepth();
+ }
+ }
+
+ ol.popGeneratorState();
+ // ------
+
+ endFile(ol); // contains ol.endContents()
+ ol.popGeneratorState();
+}
+
+//----------------------------------------------------------------------------
+
+static void writeAnnotatedInterfaceIndex(OutputList &ol)
+{
+ //printf("writeAnnotatedInterfaceIndex: count=%d printed=%d\n",
+ // annotatedInterfaces,annotatedInterfacesPrinted);
+ if (annotatedInterfaces==0) return;
+
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::Man);
+ if (annotatedInterfacesPrinted==0)
+ {
+ ol.disable(OutputGenerator::Latex);
+ ol.disable(OutputGenerator::RTF);
+ }
+ LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::InterfaceList);
+ if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Interfaces); // fall back
+ QCString title = lne ? lne->title() : theTranslator->trInterfaceList();
+ bool addToIndex = lne==0 || lne->visible();
+
+ startFile(ol,"annotatedinterfaces",0,title,HLI_AnnotatedInterfaces);
+
+ startTitle(ol,0);
+ ol.parseText(title);
+ endTitle(ol,0,0);
+
+ ol.startContents();
+
+ ol.startTextBlock();
+ ol.parseText(lne ? lne->intro() : theTranslator->trInterfaceListDescription());
+ ol.endTextBlock();
+
+ // ---------------
+ // Linear interface index for Latex/RTF
+ // ---------------
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::Html);
+ Doxygen::indexList->disable();
+
+ writeAnnotatedClassList(ol, ClassDef::Interface);
+
+ Doxygen::indexList->enable();
+ ol.popGeneratorState();
+
+ // ---------------
+ // Hierarchical interface index for HTML
+ // ---------------
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Html);
+
+ {
+ if (addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(TRUE,title,0,"annotatedinterfaces",0,TRUE,TRUE);
+ Doxygen::indexList->incContentsDepth();
+ }
+ FTVHelp* ftv = new FTVHelp(FALSE);
+ writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex,ClassDef::Interface);
+ writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE,ClassDef::Interface);
+ QGString outStr;
+ FTextStream t(&outStr);
+ ftv->generateTreeViewInline(t);
+ ol.writeString(outStr);
+ delete ftv;
+ if (addToIndex)
+ {
+ Doxygen::indexList->decContentsDepth();
+ }
+ }
+
+ ol.popGeneratorState();
+ // ------
+
+ endFile(ol); // contains ol.endContents()
+ ol.popGeneratorState();
+}
+
+//----------------------------------------------------------------------------
+
+static void writeAnnotatedStructIndex(OutputList &ol)
+{
+ //printf("writeAnnotatedStructIndex: count=%d printed=%d\n",
+ // annotatedStructs,annotatedStructsPrinted);
+ if (annotatedStructs==0) return;
+
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::Man);
+ if (annotatedStructsPrinted==0)
+ {
+ ol.disable(OutputGenerator::Latex);
+ ol.disable(OutputGenerator::RTF);
+ }
+ LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::StructList);
+ if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Structs); // fall back
+ QCString title = lne ? lne->title() : theTranslator->trStructList();
+ bool addToIndex = lne==0 || lne->visible();
+
+ startFile(ol,"annotatedstructs",0,title,HLI_AnnotatedStructs);
+
+ startTitle(ol,0);
+ ol.parseText(title);
+ endTitle(ol,0,0);
+
+ ol.startContents();
+
+ ol.startTextBlock();
+ ol.parseText(lne ? lne->intro() : theTranslator->trStructListDescription());
+ ol.endTextBlock();
+
+ // ---------------
+ // Linear struct index for Latex/RTF
+ // ---------------
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::Html);
+ Doxygen::indexList->disable();
+
+ writeAnnotatedClassList(ol, ClassDef::Struct);
+
+ Doxygen::indexList->enable();
+ ol.popGeneratorState();
+
+ // ---------------
+ // Hierarchical struct index for HTML
+ // ---------------
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Html);
+
+ {
+ if (addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(TRUE,title,0,"annotatedstructs",0,TRUE,TRUE);
+ Doxygen::indexList->incContentsDepth();
+ }
+ FTVHelp* ftv = new FTVHelp(FALSE);
+ writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex,ClassDef::Struct);
+ writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE,ClassDef::Struct);
+ QGString outStr;
+ FTextStream t(&outStr);
+ ftv->generateTreeViewInline(t);
+ ol.writeString(outStr);
+ delete ftv;
+ if (addToIndex)
+ {
+ Doxygen::indexList->decContentsDepth();
+ }
+ }
+
+ ol.popGeneratorState();
+ // ------
+
+ endFile(ol); // contains ol.endContents()
+ ol.popGeneratorState();
+}
+
+//----------------------------------------------------------------------------
+
+static void writeAnnotatedExceptionIndex(OutputList &ol)
+{
+ //printf("writeAnnotatedExceptionIndex: count=%d printed=%d\n",
+ // annotatedExceptions,annotatedExceptionsPrinted);
+ if (annotatedExceptions==0) return;
+
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::Man);
+ if (annotatedExceptionsPrinted==0)
+ {
+ ol.disable(OutputGenerator::Latex);
+ ol.disable(OutputGenerator::RTF);
+ }
+ LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ExceptionList);
+ if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Exceptions); // fall back
+ QCString title = lne ? lne->title() : theTranslator->trExceptionList();
+ bool addToIndex = lne==0 || lne->visible();
+
+ startFile(ol,"annotatedexceptions",0,title,HLI_AnnotatedExceptions);
+
+ startTitle(ol,0);
+ ol.parseText(title);
+ endTitle(ol,0,0);
+
+ ol.startContents();
+
+ ol.startTextBlock();
+ ol.parseText(lne ? lne->intro() : theTranslator->trExceptionListDescription());
+ ol.endTextBlock();
+
+ // ---------------
+ // Linear interface index for Latex/RTF
+ // ---------------
+ ol.pushGeneratorState();
+ ol.disable(OutputGenerator::Html);
+ Doxygen::indexList->disable();
+
+ writeAnnotatedClassList(ol, ClassDef::Exception);
+
+ Doxygen::indexList->enable();
+ ol.popGeneratorState();
+
+ // ---------------
+ // Hierarchical interface index for HTML
+ // ---------------
+ ol.pushGeneratorState();
+ ol.disableAllBut(OutputGenerator::Html);
+
+ {
+ if (addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(TRUE,title,0,"annotatedexceptions",0,TRUE,TRUE);
+ Doxygen::indexList->incContentsDepth();
+ }
+ FTVHelp* ftv = new FTVHelp(FALSE);
+ writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex,ClassDef::Exception);
+ writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE,ClassDef::Exception);
QGString outStr;
FTextStream t(&outStr);
ftv->generateTreeViewInline(t);
@@ -2401,6 +3003,16 @@ void addNamespaceMemberNameToIndex(MemberDef *md)
g_namespaceIndexLetterUsed[NMHL_Typedefs].append(letter,md);
documentedNamespaceMembers[NMHL_Typedefs]++;
}
+ else if (md->isSequence())
+ {
+ g_namespaceIndexLetterUsed[NMHL_Sequences].append(letter,md);
+ documentedNamespaceMembers[NMHL_Sequences]++;
+ }
+ else if (md->isDictionary())
+ {
+ g_namespaceIndexLetterUsed[NMHL_Dictionaries].append(letter,md);
+ documentedNamespaceMembers[NMHL_Dictionaries]++;
+ }
else if (md->isEnumerate())
{
g_namespaceIndexLetterUsed[NMHL_Enums].append(letter,md);
@@ -2458,6 +3070,16 @@ void addFileMemberNameToIndex(MemberDef *md)
g_fileIndexLetterUsed[FMHL_Typedefs].append(letter,md);
documentedFileMembers[FMHL_Typedefs]++;
}
+ else if (md->isSequence())
+ {
+ g_fileIndexLetterUsed[FMHL_Sequences].append(letter,md);
+ documentedFileMembers[FMHL_Sequences]++;
+ }
+ else if (md->isDictionary())
+ {
+ g_fileIndexLetterUsed[FMHL_Dictionaries].append(letter,md);
+ documentedFileMembers[FMHL_Dictionaries]++;
+ }
else if (md->isEnumerate())
{
g_fileIndexLetterUsed[FMHL_Enums].append(letter,md);
@@ -2701,6 +3323,7 @@ static const FmhlInfo *getFmhlInfo(int hl)
{
static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
static FmhlInfo fmhlInfo[] =
{
FmhlInfo("globals", theTranslator->trAll()),
@@ -2708,8 +3331,10 @@ static const FmhlInfo *getFmhlInfo(int hl)
fortranOpt ? theTranslator->trSubprograms() :
vhdlOpt ? theTranslator->trFunctionAndProc() :
theTranslator->trFunctions()),
- FmhlInfo("globals_vars",theTranslator->trVariables()),
+ FmhlInfo("globals_vars",sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables()),
FmhlInfo("globals_type",theTranslator->trTypedefs()),
+ FmhlInfo("globals_sequ",theTranslator->trSequences()),
+ FmhlInfo("globals_dict",theTranslator->trDictionaries()),
FmhlInfo("globals_enum",theTranslator->trEnumerations()),
FmhlInfo("globals_eval",theTranslator->trEnumerationValues()),
FmhlInfo("globals_defs",theTranslator->trDefines())
@@ -2845,6 +3470,8 @@ static void writeFileMemberIndex(OutputList &ol)
writeFileMemberIndexFiltered(ol,FMHL_Functions);
writeFileMemberIndexFiltered(ol,FMHL_Variables);
writeFileMemberIndexFiltered(ol,FMHL_Typedefs);
+ writeFileMemberIndexFiltered(ol,FMHL_Sequences);
+ writeFileMemberIndexFiltered(ol,FMHL_Dictionaries);
writeFileMemberIndexFiltered(ol,FMHL_Enums);
writeFileMemberIndexFiltered(ol,FMHL_EnumValues);
writeFileMemberIndexFiltered(ol,FMHL_Defines);
@@ -2869,6 +3496,7 @@ static const NmhlInfo *getNmhlInfo(int hl)
{
static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
static NmhlInfo nmhlInfo[] =
{
NmhlInfo("namespacemembers", theTranslator->trAll()),
@@ -2876,8 +3504,10 @@ static const NmhlInfo *getNmhlInfo(int hl)
fortranOpt ? theTranslator->trSubprograms() :
vhdlOpt ? theTranslator->trFunctionAndProc() :
theTranslator->trFunctions()),
- NmhlInfo("namespacemembers_vars",theTranslator->trVariables()),
+ NmhlInfo("namespacemembers_vars",sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables()),
NmhlInfo("namespacemembers_type",theTranslator->trTypedefs()),
+ NmhlInfo("namespacemembers_sequ",theTranslator->trSequences()),
+ NmhlInfo("namespacemembers_dict",theTranslator->trDictionaries()),
NmhlInfo("namespacemembers_enum",theTranslator->trEnumerations()),
NmhlInfo("namespacemembers_eval",theTranslator->trEnumerationValues())
};
@@ -3017,6 +3647,8 @@ static void writeNamespaceMemberIndex(OutputList &ol)
writeNamespaceMemberIndexFiltered(ol,NMHL_Functions);
writeNamespaceMemberIndexFiltered(ol,NMHL_Variables);
writeNamespaceMemberIndexFiltered(ol,NMHL_Typedefs);
+ writeNamespaceMemberIndexFiltered(ol,NMHL_Sequences);
+ writeNamespaceMemberIndexFiltered(ol,NMHL_Dictionaries);
writeNamespaceMemberIndexFiltered(ol,NMHL_Enums);
writeNamespaceMemberIndexFiltered(ol,NMHL_EnumValues);
if (documentedNamespaceMembers[NMHL_All]>0 && addToIndex)
@@ -4043,6 +4675,12 @@ static void writeIndex(OutputList &ol)
ol.parseText(/*projPrefix+*/(fortranOpt?theTranslator->trModulesIndex():theTranslator->trNamespaceIndex()));
ol.endIndexSection(isNamespaceIndex);
}
+ if (hierarchyInterfaces>0)
+ {
+ ol.startIndexSection(isClassHierarchyIndex);
+ ol.parseText(/*projPrefix+*/theTranslator->trHierarchicalIndex());
+ ol.endIndexSection(isClassHierarchyIndex);
+ }
if (hierarchyClasses>0)
{
ol.startIndexSection(isClassHierarchyIndex);
@@ -4053,6 +4691,18 @@ static void writeIndex(OutputList &ol)
));
ol.endIndexSection(isClassHierarchyIndex);
}
+ if (hierarchyExceptions>0)
+ {
+ ol.startIndexSection(isClassHierarchyIndex);
+ ol.parseText(/*projPrefix+*/theTranslator->trHierarchicalIndex());
+ ol.endIndexSection(isClassHierarchyIndex);
+ }
+ if (annotatedInterfacesPrinted>0)
+ {
+ ol.startIndexSection(isCompoundIndex);
+ ol.parseText(/*projPrefix+*/theTranslator->trInterfaceIndex());
+ ol.endIndexSection(isCompoundIndex);
+ }
if (annotatedClassesPrinted>0)
{
ol.startIndexSection(isCompoundIndex);
@@ -4063,6 +4713,18 @@ static void writeIndex(OutputList &ol)
));
ol.endIndexSection(isCompoundIndex);
}
+ if (annotatedStructsPrinted>0)
+ {
+ ol.startIndexSection(isCompoundIndex);
+ ol.parseText(/*projPrefix+*/theTranslator->trStructIndex());
+ ol.endIndexSection(isCompoundIndex);
+ }
+ if (annotatedExceptionsPrinted>0)
+ {
+ ol.startIndexSection(isCompoundIndex);
+ ol.parseText(/*projPrefix+*/theTranslator->trExceptionIndex());
+ ol.endIndexSection(isCompoundIndex);
+ }
if (documentedFiles>0)
{
ol.startIndexSection(isFileIndex);
@@ -4084,12 +4746,30 @@ static void writeIndex(OutputList &ol)
ol.parseText(/*projPrefix+*/(fortranOpt?theTranslator->trModuleDocumentation():theTranslator->trNamespaceDocumentation()));
ol.endIndexSection(isNamespaceDocumentation);
}
+ if (annotatedInterfacesPrinted>0)
+ {
+ ol.startIndexSection(isClassDocumentation);
+ ol.parseText(/*projPrefix+*/theTranslator->trInterfaceDocumentation());
+ ol.endIndexSection(isClassDocumentation);
+ }
if (annotatedClassesPrinted>0)
{
ol.startIndexSection(isClassDocumentation);
ol.parseText(/*projPrefix+*/(fortranOpt?theTranslator->trTypeDocumentation():theTranslator->trClassDocumentation()));
ol.endIndexSection(isClassDocumentation);
}
+ if (annotatedStructsPrinted>0)
+ {
+ ol.startIndexSection(isClassDocumentation);
+ ol.parseText(/*projPrefix+*/theTranslator->trStructDocumentation());
+ ol.endIndexSection(isClassDocumentation);
+ }
+ if (annotatedExceptionsPrinted>0)
+ {
+ ol.startIndexSection(isClassDocumentation);
+ ol.parseText(/*projPrefix+*/theTranslator->trExceptionDocumentation());
+ ol.endIndexSection(isClassDocumentation);
+ }
if (documentedFiles>0)
{
ol.startIndexSection(isFileDocumentation);
@@ -4128,6 +4808,7 @@ static QArray<bool> indexWritten;
static void writeIndexHierarchyEntries(OutputList &ol,const QList<LayoutNavEntry> &entries)
{
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
QListIterator<LayoutNavEntry> li(entries);
LayoutNavEntry *lne;
for (li.toFirst();(lne=li.current());++li)
@@ -4225,8 +4906,101 @@ static void writeIndexHierarchyEntries(OutputList &ol,const QList<LayoutNavEntry
}
break;
case LayoutNavEntry::ClassMembers:
- msg("Generating member index...\n");
- writeClassMemberIndex(ol);
+ if (!sliceOpt)
+ {
+ msg("Generating member index...\n");
+ writeClassMemberIndex(ol);
+ }
+ break;
+ case LayoutNavEntry::Interfaces:
+ if (sliceOpt && annotatedInterfaces>0 && addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,lne->baseFile(),0);
+ Doxygen::indexList->incContentsDepth();
+ needsClosing=TRUE;
+ }
+ break;
+ case LayoutNavEntry::InterfaceList:
+ if (sliceOpt)
+ {
+ msg("Generating annotated interface index...\n");
+ writeAnnotatedInterfaceIndex(ol);
+ }
+ break;
+ case LayoutNavEntry::InterfaceIndex:
+ if (sliceOpt)
+ {
+ msg("Generating alphabetical interface index...\n");
+ writeAlphabeticalInterfaceIndex(ol);
+ }
+ break;
+ case LayoutNavEntry::InterfaceHierarchy:
+ if (sliceOpt)
+ {
+ msg("Generating hierarchical interface index...\n");
+ writeHierarchicalInterfaceIndex(ol);
+ if (Config_getBool(HAVE_DOT) && Config_getBool(GRAPHICAL_HIERARCHY))
+ {
+ msg("Generating graphical interface hierarchy...\n");
+ writeGraphicalInterfaceHierarchy(ol);
+ }
+ }
+ break;
+ case LayoutNavEntry::Structs:
+ if (sliceOpt && annotatedStructs>0 && addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,lne->baseFile(),0);
+ Doxygen::indexList->incContentsDepth();
+ needsClosing=TRUE;
+ }
+ break;
+ case LayoutNavEntry::StructList:
+ if (sliceOpt)
+ {
+ msg("Generating annotated struct index...\n");
+ writeAnnotatedStructIndex(ol);
+ }
+ break;
+ case LayoutNavEntry::StructIndex:
+ if (sliceOpt)
+ {
+ msg("Generating alphabetical struct index...\n");
+ writeAlphabeticalStructIndex(ol);
+ }
+ break;
+ case LayoutNavEntry::Exceptions:
+ if (sliceOpt && annotatedExceptions>0 && addToIndex)
+ {
+ Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,lne->baseFile(),0);
+ Doxygen::indexList->incContentsDepth();
+ needsClosing=TRUE;
+ }
+ break;
+ case LayoutNavEntry::ExceptionList:
+ if (sliceOpt)
+ {
+ msg("Generating annotated exception index...\n");
+ writeAnnotatedExceptionIndex(ol);
+ }
+ break;
+ case LayoutNavEntry::ExceptionIndex:
+ if (sliceOpt)
+ {
+ msg("Generating alphabetical exception index...\n");
+ writeAlphabeticalExceptionIndex(ol);
+ }
+ break;
+ case LayoutNavEntry::ExceptionHierarchy:
+ if (sliceOpt)
+ {
+ msg("Generating hierarchical exception index...\n");
+ writeHierarchicalExceptionIndex(ol);
+ if (Config_getBool(HAVE_DOT) && Config_getBool(GRAPHICAL_HIERARCHY))
+ {
+ msg("Generating graphical exception hierarchy...\n");
+ writeGraphicalExceptionHierarchy(ol);
+ }
+ }
break;
case LayoutNavEntry::Files:
{
@@ -4308,6 +5082,9 @@ static void writeIndexHierarchyEntries(OutputList &ol,const QList<LayoutNavEntry
}
writeUserGroupStubPage(ol,lne);
break;
+ case LayoutNavEntry::None:
+ assert(kind != LayoutNavEntry::None); // should never happen, means not properly initialized
+ break;
}
if (kind!=LayoutNavEntry::User && kind!=LayoutNavEntry::UserGroup) // User entry may appear multiple times
{
@@ -4337,26 +5114,40 @@ static bool quickLinkVisible(LayoutNavEntry::Kind kind)
{
static bool showFiles = Config_getBool(SHOW_FILES);
static bool showNamespaces = Config_getBool(SHOW_NAMESPACES);
+ static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
switch (kind)
{
- case LayoutNavEntry::MainPage: return TRUE;
- case LayoutNavEntry::User: return TRUE;
- case LayoutNavEntry::UserGroup: return TRUE;
- case LayoutNavEntry::Pages: return indexedPages>0;
- case LayoutNavEntry::Modules: return documentedGroups>0;
- case LayoutNavEntry::Namespaces: return documentedNamespaces>0 && showNamespaces;
- case LayoutNavEntry::NamespaceList: return documentedNamespaces>0 && showNamespaces;
- case LayoutNavEntry::NamespaceMembers: return documentedNamespaceMembers[NMHL_All]>0;
- case LayoutNavEntry::Classes: return annotatedClasses>0;
- case LayoutNavEntry::ClassList: return annotatedClasses>0;
- case LayoutNavEntry::ClassIndex: return annotatedClasses>0;
- case LayoutNavEntry::ClassHierarchy: return hierarchyClasses>0;
- case LayoutNavEntry::ClassMembers: return documentedClassMembers[CMHL_All]>0;
- case LayoutNavEntry::Files: return documentedHtmlFiles>0 && showFiles;
- case LayoutNavEntry::FileList: return documentedHtmlFiles>0 && showFiles;
- case LayoutNavEntry::FileGlobals: return documentedFileMembers[FMHL_All]>0;
- //case LayoutNavEntry::Dirs: return documentedDirs>0;
- case LayoutNavEntry::Examples: return Doxygen::exampleSDict->count()>0;
+ case LayoutNavEntry::MainPage: return TRUE;
+ case LayoutNavEntry::User: return TRUE;
+ case LayoutNavEntry::UserGroup: return TRUE;
+ case LayoutNavEntry::Pages: return indexedPages>0;
+ case LayoutNavEntry::Modules: return documentedGroups>0;
+ case LayoutNavEntry::Namespaces: return documentedNamespaces>0 && showNamespaces;
+ case LayoutNavEntry::NamespaceList: return documentedNamespaces>0 && showNamespaces;
+ case LayoutNavEntry::NamespaceMembers: return documentedNamespaceMembers[NMHL_All]>0;
+ case LayoutNavEntry::Classes: return annotatedClasses>0;
+ case LayoutNavEntry::ClassList: return annotatedClasses>0;
+ case LayoutNavEntry::ClassIndex: return annotatedClasses>0;
+ case LayoutNavEntry::ClassHierarchy: return hierarchyClasses>0;
+ case LayoutNavEntry::ClassMembers: return documentedClassMembers[CMHL_All]>0 && !sliceOpt;
+ case LayoutNavEntry::Interfaces: return annotatedInterfaces>0;
+ case LayoutNavEntry::InterfaceList: return annotatedInterfaces>0;
+ case LayoutNavEntry::InterfaceIndex: return annotatedInterfaces>0;
+ case LayoutNavEntry::InterfaceHierarchy: return hierarchyInterfaces>0;
+ case LayoutNavEntry::Structs: return annotatedStructs>0;
+ case LayoutNavEntry::StructList: return annotatedStructs>0;
+ case LayoutNavEntry::StructIndex: return annotatedStructs>0;
+ case LayoutNavEntry::Exceptions: return annotatedExceptions>0;
+ case LayoutNavEntry::ExceptionList: return annotatedExceptions>0;
+ case LayoutNavEntry::ExceptionIndex: return annotatedExceptions>0;
+ case LayoutNavEntry::ExceptionHierarchy: return hierarchyExceptions>0;
+ case LayoutNavEntry::Files: return documentedHtmlFiles>0 && showFiles;
+ case LayoutNavEntry::FileList: return documentedHtmlFiles>0 && showFiles;
+ case LayoutNavEntry::FileGlobals: return documentedFileMembers[FMHL_All]>0;
+ case LayoutNavEntry::Examples: return Doxygen::exampleSDict->count()>0;
+ case LayoutNavEntry::None: // should never happen, means not properly initialized
+ assert(kind != LayoutNavEntry::None);
+ return FALSE;
}
return FALSE;
}
diff --git a/src/index.h b/src/index.h
index ace3614..f3e0241 100644
--- a/src/index.h
+++ b/src/index.h
@@ -184,9 +184,17 @@ enum HighlightedItem
HLI_Modules,
//HLI_Directories,
HLI_Namespaces,
- HLI_Hierarchy,
+ HLI_ClassHierarchy,
+ HLI_InterfaceHierarchy,
+ HLI_ExceptionHierarchy,
HLI_Classes,
- HLI_Annotated,
+ HLI_Interfaces,
+ HLI_Structs,
+ HLI_Exceptions,
+ HLI_AnnotatedClasses,
+ HLI_AnnotatedInterfaces,
+ HLI_AnnotatedStructs,
+ HLI_AnnotatedExceptions,
HLI_Files,
HLI_NamespaceMembers,
HLI_Functions,
@@ -197,6 +205,9 @@ enum HighlightedItem
HLI_UserGroup,
HLI_ClassVisible,
+ HLI_InterfaceVisible,
+ HLI_StructVisible,
+ HLI_ExceptionVisible,
HLI_NamespaceVisible,
HLI_FileVisible
};
@@ -221,6 +232,8 @@ enum FileMemberHighlight
FMHL_Functions,
FMHL_Variables,
FMHL_Typedefs,
+ FMHL_Sequences,
+ FMHL_Dictionaries,
FMHL_Enums,
FMHL_EnumValues,
FMHL_Defines,
@@ -233,6 +246,8 @@ enum NamespaceMemberHighlight
NMHL_Functions,
NMHL_Variables,
NMHL_Typedefs,
+ NMHL_Sequences,
+ NMHL_Dictionaries,
NMHL_Enums,
NMHL_EnumValues,
NMHL_Total = NMHL_EnumValues+1
@@ -257,7 +272,12 @@ void writeIndexHierarchy(OutputList &ol);
void countDataStructures();
extern int annotatedClasses;
+extern int annotatedInterfaces;
+extern int annotatedStructs;
+extern int annotatedExceptions;
extern int hierarchyClasses;
+extern int hierarchyInterfaces;
+extern int hierarchyExceptions;
extern int documentedFiles;
extern int documentedGroups;
extern int documentedNamespaces;
diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp
index 452a481..77795ee 100644
--- a/src/latexdocvisitor.cpp
+++ b/src/latexdocvisitor.cpp
@@ -33,6 +33,7 @@
#include "filedef.h"
#include "config.h"
#include "htmlentity.h"
+#include "emoji.h"
#include "plantuml.h"
const int maxLevels=5;
@@ -48,16 +49,23 @@ static const char *getSectionName(int level)
return secLabels[QMIN(maxLevels-1,l)];
}
-static void visitPreStart(FTextStream &t, const bool hasCaption, QCString name, QCString width, QCString height)
+static void visitPreStart(FTextStream &t, bool hasCaption, QCString name, QCString width, QCString height, bool inlineImage = FALSE)
{
- if (hasCaption)
+ if (inlineImage)
{
- t << "\n\\begin{DoxyImage}\n";
+ t << "\n\\begin{DoxyInlineImage}\n";
}
else
{
- t << "\n\\begin{DoxyImageNoCaption}\n"
- " \\mbox{";
+ if (hasCaption)
+ {
+ t << "\n\\begin{DoxyImage}\n";
+ }
+ else
+ {
+ t << "\n\\begin{DoxyImageNoCaption}\n"
+ " \\mbox{";
+ }
}
t << "\\includegraphics";
@@ -80,7 +88,14 @@ static void visitPreStart(FTextStream &t, const bool hasCaption, QCString name,
if (width.isEmpty() && height.isEmpty())
{
/* default setting */
- t << "[width=\\textwidth,height=\\textheight/2,keepaspectratio=true]";
+ if (inlineImage)
+ {
+ t << "[height=\\baselineskip,keepaspectratio=true]";
+ }
+ else
+ {
+ t << "[width=\\textwidth,height=\\textheight/2,keepaspectratio=true]";
+ }
}
else
{
@@ -91,21 +106,36 @@ static void visitPreStart(FTextStream &t, const bool hasCaption, QCString name,
if (hasCaption)
{
- t << "\n\\doxyfigcaption{";
+ if (!inlineImage)
+ {
+ t << "\n\\doxyfigcaption{";
+ }
+ else
+ {
+ t << "%"; // to catch the caption
+ }
}
}
-static void visitPostEnd(FTextStream &t, const bool hasCaption)
+static void visitPostEnd(FTextStream &t, bool hasCaption, bool inlineImage = FALSE)
{
- t << "}\n"; // end mbox or caption
- if (hasCaption)
+ if (inlineImage)
{
- t << "\\end{DoxyImage}\n";
+ t << "\n\\end{DoxyInlineImage}\n";
}
- else{
- t << "\\end{DoxyImageNoCaption}\n";
+ else
+ {
+ t << "}\n"; // end mbox or caption
+ if (hasCaption)
+ {
+ t << "\\end{DoxyImage}\n";
+ }
+ else
+ {
+ t << "\\end{DoxyImageNoCaption}\n";
+ }
}
}
@@ -210,6 +240,55 @@ void LatexDocVisitor::visit(DocSymbol *s)
}
}
+void LatexDocVisitor::visit(DocEmoji *s)
+{
+ if (m_hide) return;
+ const char *res_text = EmojiEntityMapper::instance()->text(s->emoji());
+ if (res_text)
+ {
+ const char *res_code = EmojiEntityMapper::instance()->code(s->emoji());
+ m_t << "\\doxygenemoji{";
+ filter(res_text);
+ m_t << "}{";
+ m_t << res_code;
+ m_t << "}{";
+ const char *p = res_code;
+ char res[10];
+ int i = 0;
+ bool first = TRUE;
+ while (*p)
+ {
+ switch(*p)
+ {
+ case '&': case '#': case 'x':
+ break;
+ case ';':
+ res[i] = '\0';
+ if (!first) m_t << "-";
+ m_t << res;
+ first = FALSE;
+ i = 0;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ res[i] = *p;
+ i++;
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ res[i] = *p -'a' + 'A'; // so it is uppercase
+ i++;
+ break;
+ }
+ p++;
+ }
+ m_t << "}";
+ }
+ else
+ {
+ err("LaTeX: non supported Emoji-entity found: %s\n",EmojiEntityMapper::instance()->html(s->emoji()));
+ }
+}
+
void LatexDocVisitor::visit(DocURL *u)
{
if (m_hide) return;
@@ -217,11 +296,11 @@ void LatexDocVisitor::visit(DocURL *u)
{
m_t << "\\href{";
if (u->isEmail()) m_t << "mailto:";
- m_t << u->url() << "}";
+ m_t << latexFilterURL(u->url()) << "}";
}
- m_t << "\\texttt{ ";
+ m_t << "{\\texttt{ ";
filter(u->url());
- m_t << "}";
+ m_t << "}}";
}
void LatexDocVisitor::visit(DocLineBreak *)
@@ -564,9 +643,9 @@ void LatexDocVisitor::visit(DocIndexEntry *i)
{
if (m_hide) return;
m_t << "\\index{";
- m_t << latexEscapeLabelName(i->entry(),false);
+ m_t << latexEscapeLabelName(i->entry());
m_t << "@{";
- m_t << latexEscapeIndexChars(i->entry(),false);
+ m_t << latexEscapeIndexChars(i->entry());
m_t << "}}";
}
@@ -1252,16 +1331,16 @@ void LatexDocVisitor::visitPre(DocHRef *href)
if (Config_getBool(PDF_HYPERLINKS))
{
m_t << "\\href{";
- m_t << href->url();
+ m_t << latexFilterURL(href->url());
m_t << "}";
}
- m_t << "\\texttt{ ";
+ m_t << "{\\texttt{ ";
}
void LatexDocVisitor::visitPost(DocHRef *)
{
if (m_hide) return;
- m_t << "}";
+ m_t << "}}";
}
void LatexDocVisitor::visitPre(DocHtmlHeader *header)
@@ -1286,7 +1365,7 @@ void LatexDocVisitor::visitPre(DocImage *img)
gfxName=gfxName.left(gfxName.length()-4);
}
- visitPreStart(m_t,img->hasCaption(), gfxName, img->width(), img->height());
+ visitPreStart(m_t,img->hasCaption(), gfxName, img->width(), img->height(), img->isInlineImage());
}
else // other format -> skip
{
@@ -1300,7 +1379,7 @@ void LatexDocVisitor::visitPost(DocImage *img)
if (img->type()==DocImage::Latex)
{
if (m_hide) return;
- visitPostEnd(m_t,img->hasCaption());
+ visitPostEnd(m_t,img->hasCaption(), img->isInlineImage());
}
else // other format
{
diff --git a/src/latexdocvisitor.h b/src/latexdocvisitor.h
index 881863a..7ea8ae1 100644
--- a/src/latexdocvisitor.h
+++ b/src/latexdocvisitor.h
@@ -42,6 +42,7 @@ class LatexDocVisitor : public DocVisitor
void visit(DocLinkedWord *);
void visit(DocWhiteSpace *);
void visit(DocSymbol *);
+ void visit(DocEmoji *);
void visit(DocURL *);
void visit(DocLineBreak *);
void visit(DocHorRuler *);
diff --git a/src/latexgen.cpp b/src/latexgen.cpp
index 50d4242..94c3dd1 100644
--- a/src/latexgen.cpp
+++ b/src/latexgen.cpp
@@ -165,11 +165,6 @@ void LatexCodeGenerator::writeCodeLink(const char *ref,const char *f,
static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
static bool usePDFLatex = Config_getBool(USE_PDFLATEX);
int l = qstrlen(name);
- if (m_col+l>80)
- {
- m_t << "\n ";
- m_col=0;
- }
if (!ref && usePDFLatex && pdfHyperlinks)
{
m_t << "\\mbox{\\hyperlink{";
@@ -485,6 +480,10 @@ static void writeDefaultHeaderPart1(FTextStream &t)
if (Config_getBool(LATEX_BATCHMODE))
t << "\\batchmode\n";
+ // to overcome problems wit too many open files
+ t << "\\let\\mypdfximage\\pdfximage"
+ "\\def\\pdfximage{\\immediate\\mypdfximage}";
+
// Set document class depending on configuration
QCString documentClass;
if (Config_getBool(COMPACT_LATEX))
@@ -564,6 +563,18 @@ static void writeDefaultHeaderPart1(FTextStream &t)
"\\newcommand{\\+}{\\discretionary{\\mbox{\\scriptsize$\\hookleftarrow$}}{}{}}\n"
"\n";
+ QCString emojiDir=Config_getString(LATEX_EMOJI_DIRECTORY);
+ if (emojiDir.isEmpty()) emojiDir = ".";
+ emojiDir = substitute(emojiDir,"\\","/");
+ t << "% Arguments of doxygenemoji:\n"
+ "% 1) ':<text>:' form of the emoji, already \"LaTeX\"-escaped\n"
+ "% 2) unicode of the emoji inlorm like: 'U+1F603' or 'U+0031U+FE0FU+20E3' depending on the emoji\n"
+ "% 3) file name in form like: '1F603' or '0031-FE0F-20E3' depending on the emoji\n"
+ "% in case image exist use this otherwise use the ':<text>:' form\n";
+ t << "\\newcommand{\\doxygenemoji}[3]{%\n"
+ " \\IfFileExists{" << emojiDir << "/#3.png}{\\raisebox{-0.1em}{\\includegraphics[height=0.9em]{" << emojiDir << "/#3.png}}}{#1}%\n"
+ "}\n";
+
// Define page & text layout
QCString paperName=Config_getEnum(PAPER_TYPE);
// "a4wide" package is obsolete (see bug 563698)
@@ -1369,12 +1380,12 @@ void LatexGenerator::startHtmlLink(const char *url)
t << url;
t << "}";
}
- t << "\\texttt{ ";
+ t << "{\\texttt{ ";
}
void LatexGenerator::endHtmlLink()
{
- t << "}";
+ t << "}}";
}
//void LatexGenerator::writeMailLink(const char *url)
@@ -1519,9 +1530,9 @@ void LatexGenerator::endTitleHead(const char *fileName,const char *name)
if (name)
{
t << "\\label{" << stripPath(fileName) << "}\\index{";
- t << latexEscapeLabelName(name,insideTabbing);
+ t << latexEscapeLabelName(name);
t << "@{";
- t << latexEscapeIndexChars(name,insideTabbing);
+ t << latexEscapeIndexChars(name);
t << "}}" << endl;
}
}
@@ -1602,27 +1613,27 @@ void LatexGenerator::startMemberDoc(const char *clname,
t << "\\index{";
if (clname)
{
- t << latexEscapeLabelName(clname,insideTabbing);
+ t << latexEscapeLabelName(clname);
t << "@{";
- t << latexEscapeIndexChars(clname,insideTabbing);
+ t << latexEscapeIndexChars(clname);
t << "}!";
}
- t << latexEscapeLabelName(memname,insideTabbing);
+ t << latexEscapeLabelName(memname);
t << "@{";
- t << latexEscapeIndexChars(memname,insideTabbing);
+ t << latexEscapeIndexChars(memname);
t << "}}" << endl;
t << "\\index{";
- t << latexEscapeLabelName(memname,insideTabbing);
+ t << latexEscapeLabelName(memname);
t << "@{";
- t << latexEscapeIndexChars(memname,insideTabbing);
+ t << latexEscapeIndexChars(memname);
t << "}";
if (clname)
{
t << "!";
- t << latexEscapeLabelName(clname,insideTabbing);
+ t << latexEscapeLabelName(clname);
t << "@{";
- t << latexEscapeIndexChars(clname,insideTabbing);
+ t << latexEscapeIndexChars(clname);
t << "}";
}
t << "}" << endl;
@@ -1640,7 +1651,7 @@ void LatexGenerator::startMemberDoc(const char *clname,
{
t << "\\texorpdfstring{";
}
- t << latexEscapeIndexChars(title,insideTabbing);
+ t << latexEscapeIndexChars(title);
if (pdfHyperlinks)
{
t << "}{" << latexEscapePDFString(title) << "}";
@@ -1715,16 +1726,16 @@ void LatexGenerator::addIndexItem(const char *s1,const char *s2)
if (s1)
{
t << "\\index{";
- t << latexEscapeLabelName(s1,insideTabbing);
+ t << latexEscapeLabelName(s1);
t << "@{";
- t << latexEscapeIndexChars(s1,insideTabbing);
+ t << latexEscapeIndexChars(s1);
t << "}";
if (s2)
{
t << "!";
- t << latexEscapeLabelName(s2,insideTabbing);
+ t << latexEscapeLabelName(s2);
t << "@{";
- t << latexEscapeIndexChars(s2,insideTabbing);
+ t << latexEscapeIndexChars(s2);
t << "}";
}
t << "}";
diff --git a/src/layout.cpp b/src/layout.cpp
index a3849b5..393e05d 100644
--- a/src/layout.cpp
+++ b/src/layout.cpp
@@ -50,6 +50,9 @@ static const char layout_default[] =
#define COMPILE_FOR_4_OPTIONS(def,langId1,text1,langId2,text2,langId3,text3,langId4,text4) \
COMPILE_FOR_3_OPTIONS(def,langId1,text1,langId2,text2,langId3,text3)+ADD_OPTION(langId4,text4)
+#define COMPILE_FOR_5_OPTIONS(def,langId1,text1,langId2,text2,langId3,text3,langId4,text4,langId5,text5) \
+ COMPILE_FOR_4_OPTIONS(def,langId1,text1,langId2,text2,langId3,text3,langId4,text4)+ADD_OPTION(langId5,text5)
+
static bool elemIsVisible(const QXmlAttributes &attrib,bool defVal=TRUE)
{
QCString visible = attrib.value("visible").utf8();
@@ -265,6 +268,7 @@ class LayoutParser : public QXmlDefaultHandler
//bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
//bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
//bool javaOpt = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
+ bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
// start & end handlers
m_sHandler.insert("doxygenlayout",
@@ -331,9 +335,10 @@ class LayoutParser : public QXmlDefaultHandler
m_sHandler.insert("class/memberdecl/publicmethods",
new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
MemberListType_pubMethods,
- COMPILE_FOR_1_OPTION(
+ COMPILE_FOR_2_OPTIONS(
theTranslator->trPublicMembers(),
- SrcLangExt_ObjC,theTranslator->trInstanceMethods()
+ SrcLangExt_ObjC,theTranslator->trInstanceMethods(),
+ SrcLangExt_Slice,theTranslator->trOperations()
)));
m_sHandler.insert("class/memberdecl/publicstaticmethods",
new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
@@ -344,7 +349,11 @@ class LayoutParser : public QXmlDefaultHandler
)));
m_sHandler.insert("class/memberdecl/publicattributes",
new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
- MemberListType_pubAttribs,theTranslator->trPublicAttribs()));
+ MemberListType_pubAttribs,
+ COMPILE_FOR_1_OPTION(
+ theTranslator->trPublicAttribs(),
+ SrcLangExt_Slice,theTranslator->trDataMembers()
+ )));
m_sHandler.insert("class/memberdecl/publicstaticattributes",
new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs()));
@@ -440,17 +449,22 @@ class LayoutParser : public QXmlDefaultHandler
m_sHandler.insert("class/memberdef/functions",
new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
MemberListType_functionMembers,
- COMPILE_FOR_2_OPTIONS(
+ COMPILE_FOR_3_OPTIONS(
theTranslator->trMemberFunctionDocumentation(),
SrcLangExt_ObjC,theTranslator->trMethodDocumentation(),
- SrcLangExt_Fortran,theTranslator->trMemberFunctionDocumentationFortran()
+ SrcLangExt_Fortran,theTranslator->trMemberFunctionDocumentationFortran(),
+ SrcLangExt_Slice,theTranslator->trOperationDocumentation()
)));
m_sHandler.insert("class/memberdef/related",
new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
MemberListType_relatedMembers,theTranslator->trRelatedFunctionDocumentation()));
m_sHandler.insert("class/memberdef/variables",
new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
- MemberListType_variableMembers,theTranslator->trMemberDataDocumentation()));
+ MemberListType_variableMembers,
+ COMPILE_FOR_1_OPTION(
+ theTranslator->trMemberDataDocumentation(),
+ SrcLangExt_Slice,theTranslator->trDataMemberDocumentation()
+ )));
m_sHandler.insert("class/memberdef/properties",
new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
MemberListType_propertyMembers,theTranslator->trPropertyDocumentation()));
@@ -477,16 +491,21 @@ class LayoutParser : public QXmlDefaultHandler
new StartElementHandler(this,&LayoutParser::startMemberDecl));
m_sHandler.insert("namespace/memberdecl/nestednamespaces",
new StartElementHandlerSection(this,LayoutDocEntry::NamespaceNestedNamespaces,&LayoutParser::startSectionEntry,
- COMPILE_FOR_4_OPTIONS(
+ COMPILE_FOR_5_OPTIONS(
theTranslator->trNamespaces(),
SrcLangExt_Java,theTranslator->trPackages(),
SrcLangExt_VHDL,theTranslator->trPackages(),
SrcLangExt_IDL,theTranslator->trModules(),
- SrcLangExt_Fortran,theTranslator->trModules()
- )));
+ SrcLangExt_Fortran,theTranslator->trModules(),
+ SrcLangExt_Slice,(sliceOpt ?
+ theTranslator->trModules() :
+ theTranslator->trNamespaces()))));
m_sHandler.insert("namespace/memberdecl/constantgroups",
new StartElementHandlerSection(this,LayoutDocEntry::NamespaceNestedConstantGroups,&LayoutParser::startSectionEntry,
theTranslator->trConstantGroups()));
+ m_sHandler.insert("namespace/memberdecl/interfaces",
+ new StartElementHandlerSection(this,LayoutDocEntry::NamespaceInterfaces,&LayoutParser::startSectionEntry,
+ theTranslator->trSliceInterfaces()));
m_sHandler.insert("namespace/memberdecl/classes",
new StartElementHandlerSection(this,LayoutDocEntry::NamespaceClasses,&LayoutParser::startSectionEntry,
COMPILE_FOR_2_OPTIONS(
@@ -494,11 +513,23 @@ class LayoutParser : public QXmlDefaultHandler
SrcLangExt_VHDL,theTranslator->trVhdlType(VhdlDocGen::ENTITY,FALSE),
SrcLangExt_Fortran,theTranslator->trDataTypes()
)));
+ m_sHandler.insert("namespace/memberdecl/structs",
+ new StartElementHandlerSection(this,LayoutDocEntry::NamespaceStructs,&LayoutParser::startSectionEntry,
+ theTranslator->trStructs()));
+ m_sHandler.insert("namespace/memberdecl/exceptions",
+ new StartElementHandlerSection(this,LayoutDocEntry::NamespaceExceptions,&LayoutParser::startSectionEntry,
+ theTranslator->trExceptions()));
m_sHandler.insert("namespace/memberdecl/membergroups",
new StartElementHandlerKind(this,LayoutDocEntry::MemberGroups,&LayoutParser::startSimpleEntry));
m_sHandler.insert("namespace/memberdecl/typedefs",
new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
MemberListType_decTypedefMembers,theTranslator->trTypedefs()));
+ m_sHandler.insert("namespace/memberdecl/sequences",
+ new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
+ MemberListType_decSequenceMembers,theTranslator->trSequences()));
+ m_sHandler.insert("namespace/memberdecl/dictionaries",
+ new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
+ MemberListType_decDictionaryMembers,theTranslator->trDictionaries()));
m_sHandler.insert("namespace/memberdecl/enums",
new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
MemberListType_decEnumMembers,theTranslator->trEnumerations()));
@@ -512,7 +543,8 @@ class LayoutParser : public QXmlDefaultHandler
)));
m_sHandler.insert("namespace/memberdecl/variables",
new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
- MemberListType_decVarMembers,theTranslator->trVariables()));
+ MemberListType_decVarMembers,
+ sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables()));
m_eHandler.insert("namespace/memberdecl",
new EndElementHandler(this,&LayoutParser::endMemberDecl));
m_sHandler.insert("namespace/memberdef",
@@ -526,6 +558,13 @@ class LayoutParser : public QXmlDefaultHandler
m_sHandler.insert("namespace/memberdef/typedefs",
new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation()));
+ m_sHandler.insert("namespace/memberdef/sequences",
+ new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
+ MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation()));
+ m_sHandler.insert("namespace/memberdef/dictionaries",
+ new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
+ MemberListType_docDictionaryMembers,
+ theTranslator->trDictionaryDocumentation()));
m_sHandler.insert("namespace/memberdef/enums",
new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation()));
@@ -538,7 +577,9 @@ class LayoutParser : public QXmlDefaultHandler
)));
m_sHandler.insert("namespace/memberdef/variables",
new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
- MemberListType_docVarMembers,theTranslator->trVariableDocumentation()));
+ MemberListType_docVarMembers,
+ sliceOpt ? theTranslator->trConstantDocumentation() :
+ theTranslator->trVariableDocumentation()));
m_eHandler.insert("namespace/memberdef",
new EndElementHandler(this,&LayoutParser::endMemberDef));
m_eHandler.insert("namespace",
@@ -566,6 +607,9 @@ class LayoutParser : public QXmlDefaultHandler
new StartElementHandlerKind(this,LayoutDocEntry::MemberGroups,&LayoutParser::startSimpleEntry));
m_sHandler.insert("file/memberdecl",
new StartElementHandler(this,&LayoutParser::startMemberDecl));
+ m_sHandler.insert("file/memberdecl/interfaces",
+ new StartElementHandlerSection(this,LayoutDocEntry::FileInterfaces,&LayoutParser::startSectionEntry,
+ theTranslator->trSliceInterfaces()));
m_sHandler.insert("file/memberdecl/classes",
new StartElementHandlerSection(this,LayoutDocEntry::FileClasses,&LayoutParser::startSectionEntry,
COMPILE_FOR_2_OPTIONS(
@@ -573,13 +617,20 @@ class LayoutParser : public QXmlDefaultHandler
SrcLangExt_VHDL,theTranslator->trVhdlType(VhdlDocGen::ENTITY,FALSE),
SrcLangExt_Fortran,theTranslator->trDataTypes()
)));
+ m_sHandler.insert("file/memberdecl/structs",
+ new StartElementHandlerSection(this,LayoutDocEntry::FileStructs,&LayoutParser::startSectionEntry,
+ theTranslator->trStructs()));
+ m_sHandler.insert("file/memberdecl/exceptions",
+ new StartElementHandlerSection(this,LayoutDocEntry::FileExceptions,&LayoutParser::startSectionEntry,
+ theTranslator->trExceptions()));
m_sHandler.insert("file/memberdecl/namespaces",
new StartElementHandlerSection(this,LayoutDocEntry::FileNamespaces,&LayoutParser::startSectionEntry,
- COMPILE_FOR_3_OPTIONS(
+ COMPILE_FOR_4_OPTIONS(
theTranslator->trNamespaces(),
SrcLangExt_Java,theTranslator->trPackages(),
SrcLangExt_IDL,theTranslator->trModules(),
- SrcLangExt_Fortran,theTranslator->trModules()
+ SrcLangExt_Fortran,theTranslator->trModules(),
+ SrcLangExt_Slice,theTranslator->trModules()
)));
m_sHandler.insert("file/memberdecl/constantgroups",
new StartElementHandlerSection(this,LayoutDocEntry::FileConstantGroups,&LayoutParser::startSectionEntry,
@@ -590,6 +641,12 @@ class LayoutParser : public QXmlDefaultHandler
m_sHandler.insert("file/memberdecl/typedefs",
new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
MemberListType_decTypedefMembers,theTranslator->trTypedefs()));
+ m_sHandler.insert("file/memberdecl/sequences",
+ new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
+ MemberListType_decSequenceMembers,theTranslator->trSequences()));
+ m_sHandler.insert("file/memberdecl/dictionaries",
+ new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
+ MemberListType_decDictionaryMembers,theTranslator->trDictionaries()));
m_sHandler.insert("file/memberdecl/enums",
new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
MemberListType_decEnumMembers,theTranslator->trEnumerations()));
@@ -603,7 +660,8 @@ class LayoutParser : public QXmlDefaultHandler
)));
m_sHandler.insert("file/memberdecl/variables",
new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
- MemberListType_decVarMembers,theTranslator->trVariables()));
+ MemberListType_decVarMembers,
+ sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables()));
m_eHandler.insert("file/memberdecl",
new EndElementHandler(this,&LayoutParser::endMemberDecl));
@@ -621,6 +679,13 @@ class LayoutParser : public QXmlDefaultHandler
m_sHandler.insert("file/memberdef/typedefs",
new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation()));
+ m_sHandler.insert("file/memberdef/sequences",
+ new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
+ MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation()));
+ m_sHandler.insert("file/memberdef/dictionaries",
+ new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
+ MemberListType_docDictionaryMembers,
+ theTranslator->trDictionaryDocumentation()));
m_sHandler.insert("file/memberdef/enums",
new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
MemberListType_docEnumMembers,
@@ -689,6 +754,12 @@ class LayoutParser : public QXmlDefaultHandler
m_sHandler.insert("group/memberdecl/typedefs",
new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
MemberListType_decTypedefMembers,theTranslator->trTypedefs()));
+ m_sHandler.insert("group/memberdecl/sequences",
+ new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
+ MemberListType_decSequenceMembers,theTranslator->trSequences()));
+ m_sHandler.insert("group/memberdecl/dictionaries",
+ new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
+ MemberListType_decDictionaryMembers,theTranslator->trDictionaries()));
m_sHandler.insert("group/memberdecl/enums",
new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry,
MemberListType_decEnumMembers,theTranslator->trEnumerations()));
@@ -745,6 +816,13 @@ class LayoutParser : public QXmlDefaultHandler
m_sHandler.insert("group/memberdef/typedefs",
new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation()));
+ m_sHandler.insert("group/memberdef/sequences",
+ new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
+ MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation()));
+ m_sHandler.insert("group/memberdef/dictionaries",
+ new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
+ MemberListType_docDictionaryMembers,
+ theTranslator->trDictionaryDocumentation()));
m_sHandler.insert("group/memberdef/enums",
new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry,
MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation()));
@@ -897,6 +975,7 @@ class LayoutParser : public QXmlDefaultHandler
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);
static bool hasGraphicalHierarchy = Config_getBool(HAVE_DOT) &&
Config_getBool(GRAPHICAL_HIERARCHY);
static bool extractAll = Config_getBool(EXTRACT_ALL);
@@ -933,23 +1012,23 @@ class LayoutParser : public QXmlDefaultHandler
},
{ "namespaces",
LayoutNavEntry::Namespaces,
- javaOpt || vhdlOpt ? theTranslator->trPackages() : fortranOpt ? theTranslator->trModules() : theTranslator->trNamespaces(),
- javaOpt || vhdlOpt ? theTranslator->trPackages() : fortranOpt ? theTranslator->trModulesList() : theTranslator->trNamespaceList(),
- javaOpt || vhdlOpt ? theTranslator->trPackageListDescription() : fortranOpt ? theTranslator->trModulesListDescription(extractAll) : theTranslator->trNamespaceListDescription(extractAll),
+ javaOpt || vhdlOpt ? theTranslator->trPackages() : fortranOpt || sliceOpt ? theTranslator->trModules() : theTranslator->trNamespaces(),
+ javaOpt || vhdlOpt ? theTranslator->trPackages() : fortranOpt || sliceOpt ? theTranslator->trModulesList() : theTranslator->trNamespaceList(),
+ javaOpt || vhdlOpt ? theTranslator->trPackageListDescription() : fortranOpt || sliceOpt ? theTranslator->trModulesListDescription(extractAll) : theTranslator->trNamespaceListDescription(extractAll),
"namespaces"
},
{ "namespacelist",
LayoutNavEntry::NamespaceList,
- javaOpt || vhdlOpt ? theTranslator->trPackages() : fortranOpt ? theTranslator->trModulesList() : theTranslator->trNamespaceList(),
+ javaOpt || vhdlOpt ? theTranslator->trPackages() : fortranOpt || sliceOpt ? theTranslator->trModulesList() : theTranslator->trNamespaceList(),
QCString(),
- javaOpt || vhdlOpt ? theTranslator->trPackageListDescription() : fortranOpt ? theTranslator->trModulesListDescription(extractAll) : theTranslator->trNamespaceListDescription(extractAll),
+ javaOpt || vhdlOpt ? theTranslator->trPackageListDescription() : fortranOpt || sliceOpt ? theTranslator->trModulesListDescription(extractAll) : theTranslator->trNamespaceListDescription(extractAll),
"namespaces"
},
{ "namespacemembers",
LayoutNavEntry::NamespaceMembers,
- javaOpt || vhdlOpt ? theTranslator->trPackageMembers() : fortranOpt ? theTranslator->trModulesMembers() : theTranslator->trNamespaceMembers(),
+ javaOpt || vhdlOpt ? theTranslator->trPackageMembers() : fortranOpt || sliceOpt ? theTranslator->trModulesMembers() : theTranslator->trNamespaceMembers(),
QCString(),
- fortranOpt ? theTranslator->trModulesMemberDescription(extractAll) : theTranslator->trNamespaceMemberDescription(extractAll),
+ fortranOpt || sliceOpt ? theTranslator->trModulesMemberDescription(extractAll) : theTranslator->trNamespaceMemberDescription(extractAll),
"namespacemembers"
},
{ "classindex",
@@ -987,6 +1066,83 @@ class LayoutParser : public QXmlDefaultHandler
fortranOpt ? theTranslator->trCompoundMembersDescriptionFortran(extractAll) : theTranslator->trCompoundMembersDescription(extractAll),
"functions"
},
+ { "interfaceindex",
+ LayoutNavEntry::InterfaceIndex,
+ theTranslator->trInterfaceIndex(),
+ QCString(),
+ QCString(),
+ "interfaces"
+ },
+ { "interfaces",
+ LayoutNavEntry::Interfaces,
+ theTranslator->trSliceInterfaces(),
+ theTranslator->trInterfaceList(),
+ theTranslator->trInterfaceListDescription(),
+ "annotatedinterfaces"
+ },
+ { "interfacelist",
+ LayoutNavEntry::InterfaceList,
+ theTranslator->trInterfaceList(),
+ QCString(),
+ theTranslator->trInterfaceListDescription(),
+ "annotatedinterfaces"
+ },
+ { "interfacehierarchy",
+ LayoutNavEntry::InterfaceHierarchy,
+ theTranslator->trInterfaceHierarchy(),
+ QCString(),
+ theTranslator->trInterfaceHierarchyDescription(),
+ hasGraphicalHierarchy ? "interfaceinherits" : "interfacehierarchy"
+ },
+ { "structindex",
+ LayoutNavEntry::StructIndex,
+ theTranslator->trStructIndex(),
+ QCString(),
+ QCString(),
+ "structs"
+ },
+ { "structs",
+ LayoutNavEntry::Structs,
+ theTranslator->trStructs(),
+ theTranslator->trStructList(),
+ theTranslator->trStructListDescription(),
+ "annotatedstructs"
+ },
+ { "structlist",
+ LayoutNavEntry::StructList,
+ theTranslator->trStructList(),
+ QCString(),
+ theTranslator->trStructListDescription(),
+ "annotatedstructs"
+ },
+ { "exceptionindex",
+ LayoutNavEntry::ExceptionIndex,
+ theTranslator->trExceptionIndex(),
+ QCString(),
+ QCString(),
+ "exceptions"
+ },
+ { "exceptions",
+ LayoutNavEntry::Exceptions,
+ theTranslator->trExceptions(),
+ theTranslator->trExceptionList(),
+ theTranslator->trExceptionListDescription(),
+ "annotatedexceptions"
+ },
+ { "exceptionlist",
+ LayoutNavEntry::ExceptionList,
+ theTranslator->trExceptionList(),
+ QCString(),
+ theTranslator->trExceptionListDescription(),
+ "annotatedexceptions"
+ },
+ { "exceptionhierarchy",
+ LayoutNavEntry::ExceptionHierarchy,
+ theTranslator->trExceptionHierarchy(),
+ QCString(),
+ theTranslator->trExceptionHierarchyDescription(),
+ hasGraphicalHierarchy ? "exceptioninherits" : "exceptionhierarchy"
+ },
{ "files",
LayoutNavEntry::Files,
theTranslator->trFile(TRUE,FALSE),
diff --git a/src/layout.h b/src/layout.h
index 1906a3d..b25aa4e 100644
--- a/src/layout.h
+++ b/src/layout.h
@@ -46,10 +46,11 @@ struct LayoutDocEntry
// Namespace specific items
NamespaceNestedNamespaces, NamespaceNestedConstantGroups,
- NamespaceClasses, NamespaceInlineClasses,
+ NamespaceClasses, NamespaceInterfaces, NamespaceStructs, NamespaceExceptions,
+ NamespaceInlineClasses,
// File specific items
- FileClasses, FileNamespaces, FileConstantGroups,
+ FileClasses, FileInterfaces, FileStructs, FileExceptions, FileConstantGroups, FileNamespaces,
FileIncludes, FileIncludeGraph,
FileIncludedByGraph, FileSourceLink,
FileInlineClasses,
@@ -131,10 +132,20 @@ struct LayoutNavEntry
ClassIndex,
ClassHierarchy,
ClassMembers,
+ Interfaces,
+ InterfaceList,
+ InterfaceIndex,
+ InterfaceHierarchy,
+ Structs,
+ StructList,
+ StructIndex,
+ Exceptions,
+ ExceptionList,
+ ExceptionIndex,
+ ExceptionHierarchy,
Files,
FileList,
FileGlobals,
- //Dirs,
Examples,
User,
UserGroup
diff --git a/src/layout_default.xml b/src/layout_default.xml
index f087958..373bb20 100644
--- a/src/layout_default.xml
+++ b/src/layout_default.xml
@@ -9,12 +9,26 @@
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab>
+ <tab type="interfaces" visible="yes" title="">
+ <tab type="interfacelist" visible="yes" title="" intro=""/>
+ <tab type="interfaceindex" visible="$ALPHABETICAL_INDEX" title=""/>
+ <tab type="interfacehierarchy" visible="yes" title="" intro=""/>
+ </tab>
<tab type="classes" visible="yes" title="">
<tab type="classlist" visible="yes" title="" intro=""/>
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="hierarchy" visible="yes" title="" intro=""/>
<tab type="classmembers" visible="yes" title="" intro=""/>
</tab>
+ <tab type="structs" visible="yes" title="">
+ <tab type="structlist" visible="yes" title="" intro=""/>
+ <tab type="structindex" visible="$ALPHABETICAL_INDEX" title=""/>
+ </tab>
+ <tab type="exceptions" visible="yes" title="">
+ <tab type="exceptionlist" visible="yes" title="" intro=""/>
+ <tab type="exceptionindex" visible="$ALPHABETICAL_INDEX" title=""/>
+ <tab type="exceptionhierarchy" visible="yes" title="" intro=""/>
+ </tab>
<tab type="files" visible="yes" title="">
<tab type="filelist" visible="yes" title="" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
@@ -87,8 +101,13 @@
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
+ <interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
+ <structs visible="yes" title=""/>
+ <exceptions visible="yes" title=""/>
<typedefs title=""/>
+ <sequences title=""/>
+ <dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
@@ -98,6 +117,8 @@
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
+ <sequences title=""/>
+ <dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
@@ -113,11 +134,16 @@
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
<sourcelink visible="yes"/>
<memberdecl>
+ <interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
+ <structs visible="yes" title=""/>
+ <exceptions visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
+ <sequences title=""/>
+ <dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
@@ -128,6 +154,8 @@
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
+ <sequences title=""/>
+ <dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
@@ -147,6 +175,8 @@
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
+ <sequences title=""/>
+ <dictionaries title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
@@ -166,6 +196,8 @@
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
+ <sequences title=""/>
+ <dictionaries title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp
index e09cc8e..8a9e6c1 100644
--- a/src/mandocvisitor.cpp
+++ b/src/mandocvisitor.cpp
@@ -30,6 +30,7 @@
#include "parserintf.h"
#include "filedef.h"
#include "htmlentity.h"
+#include "emoji.h"
ManDocVisitor::ManDocVisitor(FTextStream &t,CodeOutputInterface &ci,
const char *langExt)
@@ -89,6 +90,22 @@ void ManDocVisitor::visit(DocSymbol *s)
m_firstCol=FALSE;
}
+void ManDocVisitor::visit(DocEmoji *s)
+{
+ if (m_hide) return;
+ const char *res = EmojiEntityMapper::instance()->man(s->emoji());
+ if (res)
+ {
+ m_t << res;
+ }
+ else
+ {
+ // no error or warning to be supplied
+ // err("man: non supported HTML-entity found: &%s;\n",get_symbol_item(s->emoji()));
+ }
+ m_firstCol=FALSE;
+}
+
void ManDocVisitor::visit(DocURL *u)
{
if (m_hide) return;
diff --git a/src/mandocvisitor.h b/src/mandocvisitor.h
index d248c87..8efc223 100644
--- a/src/mandocvisitor.h
+++ b/src/mandocvisitor.h
@@ -40,6 +40,7 @@ class ManDocVisitor : public DocVisitor
void visit(DocLinkedWord *);
void visit(DocWhiteSpace *);
void visit(DocSymbol *);
+ void visit(DocEmoji *);
void visit(DocURL *);
void visit(DocLineBreak *);
void visit(DocHorRuler *);
diff --git a/src/markdown.cpp b/src/markdown.cpp
index 65102a2..b00070e 100644
--- a/src/markdown.cpp
+++ b/src/markdown.cpp
@@ -76,7 +76,7 @@
// so for example *bla (*.txt) is cool*
#define ignoreCloseEmphChar(i) \
(data[i]=='(' || data[i]=='{' || data[i]=='[' || data[i]=='<' || \
- data[i]=='=' || data[i]=='+' || data[i]=='-' || data[i]=='\\' || \
+ data[i]=='\\' || \
data[i]=='@')
//----------
@@ -396,9 +396,11 @@ static int processEmphasis2(GrowBuf &out, const char *data, int size, char c)
data[i-1]!='\n'
)
{
- out.addStr("<strong>");
+ if (c == '~') out.addStr("<strike>");
+ else out.addStr("<strong>");
processInline(out,data,i);
- out.addStr("</strong>");
+ if (c == '~') out.addStr("</strike>");
+ else out.addStr("</strong>");
return i + 2;
}
i++;
@@ -616,7 +618,7 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size)
char c = data[0];
int ret;
- if (size>2 && data[1]!=c) // _bla or *bla
+ if (size>2 && c!='~' && data[1]!=c) // _bla or *bla
{
// whitespace cannot follow an opening emphasis
if (data[1]==' ' || data[1]=='\n' ||
@@ -635,7 +637,7 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size)
}
return ret+2;
}
- if (size>4 && data[1]==c && data[2]==c && data[3]!=c) // ___bla or ***bla
+ if (size>4 && c!='~' && data[1]==c && data[2]==c && data[3]!=c) // ___bla or ***bla
{
if (data[3]==' ' || data[3]=='\n' ||
(ret = processEmphasis3(out, data+3, size-3, c)) == 0)
@@ -647,6 +649,27 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size)
return 0;
}
+static void writeMarkdownImage(GrowBuf &out, const char *fmt, bool explicitTitle, QCString title, QCString content, QCString link, FileDef *fd)
+{
+ out.addStr("@image ");
+ out.addStr(fmt);
+ out.addStr(" ");
+ out.addStr(link.mid(fd ? 0 : 5));
+ if (!explicitTitle && !content.isEmpty())
+ {
+ out.addStr(" \"");
+ out.addStr(content);
+ out.addStr("\"");
+ }
+ else if ((content.isEmpty() || explicitTitle) && !title.isEmpty())
+ {
+ out.addStr(" \"");
+ out.addStr(title);
+ out.addStr("\"");
+ }
+ out.addStr("\n");
+}
+
static int processLink(GrowBuf &out,const char *data,int,int size)
{
QCString content;
@@ -862,20 +885,10 @@ static int processLink(GrowBuf &out,const char *data,int,int size)
(fd=findFileDef(Doxygen::imageNameDict,link,ambig)))
// assume doxygen symbol link or local image link
{
- out.addStr("@image html ");
- out.addStr(link.mid(fd ? 0 : 5));
- if (!explicitTitle && !content.isEmpty())
- {
- out.addStr(" \"");
- out.addStr(content);
- out.addStr("\"");
- }
- else if ((content.isEmpty() || explicitTitle) && !title.isEmpty())
- {
- out.addStr(" \"");
- out.addStr(title);
- out.addStr("\"");
- }
+ writeMarkdownImage(out, "html", explicitTitle, title, content, link, fd);
+ writeMarkdownImage(out, "latex", explicitTitle, title, content, link, fd);
+ writeMarkdownImage(out, "rtf", explicitTitle, title, content, link, fd);
+ writeMarkdownImage(out, "docbook", explicitTitle, title, content, link, fd);
}
else
{
@@ -1887,7 +1900,7 @@ void writeOneLineHeaderOrRuler(GrowBuf &out,const char *data,int size)
QCString id;
if (isHRuler(data,size))
{
- out.addStr("<hr>\n");
+ out.addStr("\n<hr>\n");
}
else if ((level=isAtxHeader(data,size,header,id)))
{
@@ -1934,7 +1947,7 @@ void writeOneLineHeaderOrRuler(GrowBuf &out,const char *data,int size)
out.addStr(data,size);
if (hasLineBreak(data,size))
{
- out.addStr("<br>");
+ out.addStr("\n");
}
}
}
@@ -2301,7 +2314,7 @@ static QCString processBlocks(const QCString &s,int indent)
}
else
{
- out.addStr("<hr>\n");
+ out.addStr("\n<hr>\n");
}
pi=-1;
i=end;
@@ -2500,6 +2513,7 @@ QCString processMarkdown(const QCString &fileName,const int lineNr,Entry *e,cons
// setup callback table for special characters
g_actions[(unsigned int)'_']=processEmphasis;
g_actions[(unsigned int)'*']=processEmphasis;
+ g_actions[(unsigned int)'~']=processEmphasis;
g_actions[(unsigned int)'`']=processCodeSpan;
g_actions[(unsigned int)'\\']=processSpecialCommand;
g_actions[(unsigned int)'@']=processSpecialCommand;
diff --git a/src/marshal.cpp b/src/marshal.cpp
index f0ed2e8..57ff44b 100644
--- a/src/marshal.cpp
+++ b/src/marshal.cpp
@@ -370,6 +370,8 @@ void marshalEntry(StorageIntf *s,Entry *e)
marshalBool(s,e->subGrouping);
marshalBool(s,e->callGraph);
marshalBool(s,e->callerGraph);
+ marshalBool(s,e->referencedByRelation);
+ marshalBool(s,e->referencesRelation);
marshalInt(s,(int)e->virt);
marshalQCString(s,e->args);
marshalQCString(s,e->bitfields);
@@ -409,6 +411,7 @@ void marshalEntry(StorageIntf *s,Entry *e)
marshalBool(s,e->artificial);
marshalInt(s,(int)e->groupDocType);
marshalQCString(s,e->id);
+ marshalQCString(s,e->metaData);
}
void marshalEntryTree(StorageIntf *s,Entry *e)
@@ -780,6 +783,8 @@ Entry * unmarshalEntry(StorageIntf *s)
e->subGrouping = unmarshalBool(s);
e->callGraph = unmarshalBool(s);
e->callerGraph = unmarshalBool(s);
+ e->referencedByRelation = unmarshalBool(s);
+ e->referencesRelation = unmarshalBool(s);
e->virt = (Specifier)unmarshalInt(s);
e->args = unmarshalQCString(s);
e->bitfields = unmarshalQCString(s);
@@ -823,6 +828,7 @@ Entry * unmarshalEntry(StorageIntf *s)
e->artificial = unmarshalBool(s);
e->groupDocType = (Entry::GroupDocType)unmarshalInt(s);
e->id = unmarshalQCString(s);
+ e->metaData = unmarshalQCString(s);
return e;
}
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
index 5d74270..a2fcf69 100644
--- a/src/memberdef.cpp
+++ b/src/memberdef.cpp
@@ -484,7 +484,7 @@ class MemberDefImpl
void init(Definition *def,const char *t,const char *a,const char *e,
Protection p,Specifier v,bool s,Relationship r,
MemberType mt,const ArgumentList *tal,
- const ArgumentList *al
+ const ArgumentList *al,const char *meta
);
ClassDef *classDef; // member of or related to
@@ -539,6 +539,8 @@ class MemberDefImpl
QList<ArgumentList> *defTmpArgLists; // lists of template argument lists
// (for template functions in nested template classes)
+ QCString metaData; // Slice metadata.
+
ClassDef *cachedAnonymousType; // if the member has an anonymous compound
// as its type then this is computed by
// getClassDefOfAnonymousType() and
@@ -584,6 +586,8 @@ class MemberDefImpl
bool annUsed;
bool hasCallGraph;
bool hasCallerGraph;
+ bool hasReferencedByRelation;
+ bool hasReferencesRelation;
bool explExt; // member was explicitly declared external
bool tspec; // member is a template specialization
bool groupHasDocs; // true if the entry that caused the grouping was documented
@@ -626,7 +630,7 @@ void MemberDefImpl::init(Definition *def,
const char *t,const char *a,const char *e,
Protection p,Specifier v,bool s,Relationship r,
MemberType mt,const ArgumentList *tal,
- const ArgumentList *al
+ const ArgumentList *al,const char *meta
)
{
classDef=0;
@@ -647,6 +651,8 @@ void MemberDefImpl::init(Definition *def,
defTmpArgLists=0;
hasCallGraph = FALSE;
hasCallerGraph = FALSE;
+ hasReferencedByRelation = FALSE;
+ hasReferencesRelation = FALSE;
initLines=0;
type=t;
if (mt==MemberType_Typedef) type.stripPrefix("typedef ");
@@ -709,6 +715,7 @@ void MemberDefImpl::init(Definition *def,
{
declArgList = 0;
}
+ metaData = meta;
templateMaster = 0;
classSectionSDict = 0;
docsForDefinition = TRUE;
@@ -748,17 +755,18 @@ void MemberDefImpl::init(Definition *def,
* \param tal The template arguments of this member.
* \param al The arguments of this member. This is a structured form of
* the string past as argument \a a.
+ * \param meta Slice metadata.
*/
MemberDef::MemberDef(const char *df,int dl,int dc,
const char *t,const char *na,const char *a,const char *e,
Protection p,Specifier v,bool s,Relationship r,MemberType mt,
- const ArgumentList *tal,const ArgumentList *al
+ const ArgumentList *tal,const ArgumentList *al,const char *meta
) : Definition(df,dl,dc,removeRedundantWhiteSpace(na)), visited(FALSE)
{
//printf("MemberDef::MemberDef(%s)\n",na);
m_impl = new MemberDefImpl;
- m_impl->init(this,t,a,e,p,v,s,r,mt,tal,al);
+ m_impl->init(this,t,a,e,p,v,s,r,mt,tal,al,meta);
number_of_flowkw = 1;
m_isLinkableCached = 0;
m_isConstructorCached = 0;
@@ -1401,7 +1409,7 @@ bool MemberDef::isBriefSectionVisible() const
QCString MemberDef::getDeclType() const
{
QCString ltype(m_impl->type);
- if (m_impl->mtype==MemberType_Typedef)
+ if (isTypedef() && getLanguage() != SrcLangExt_Slice)
{
ltype.prepend("typedef ");
}
@@ -1511,7 +1519,10 @@ void MemberDef::writeDeclaration(OutputList &ol,
// *** write type
QCString ltype(m_impl->type);
- if (m_impl->mtype==MemberType_Typedef) ltype.prepend("typedef ");
+ if (isTypedef() && getLanguage() != SrcLangExt_Slice)
+ {
+ ltype.prepend("typedef ");
+ }
if (isAlias())
{
ltype="using";
@@ -2426,6 +2437,10 @@ QCString MemberDef::displayDefinition() const
else
{
ldef.prepend("enum ");
+ if (isSliceLocal())
+ {
+ ldef.prepend("local ");
+ }
}
}
else if (isEnumValue())
@@ -2560,7 +2575,7 @@ void MemberDef::writeDocumentation(MemberList *ml,
QCString scopeName = scName;
QCString memAnchor = anchor();
- QCString ciname = container->name();
+ QCString ciname = container->displayName();
Definition *scopedContainer = container; // see bug 753608
if (container->definitionType()==TypeGroup)
{
@@ -2603,6 +2618,10 @@ void MemberDef::writeDocumentation(MemberList *ml,
else
{
ldef.prepend("enum ");
+ if (isSliceLocal())
+ {
+ ldef.prepend("local ");
+ }
}
}
else if (isEnumValue())
@@ -2619,6 +2638,17 @@ void MemberDef::writeDocumentation(MemberList *ml,
int i=0,l;
static QRegExp r("@[0-9]+");
+ if (lang == SrcLangExt_Slice)
+ {
+ // Remove the container scope from the member name.
+ QCString prefix = scName + sep;
+ int pos = ldef.findRev(prefix.data());
+ if(pos != -1)
+ {
+ ldef.remove(pos, prefix.length());
+ }
+ }
+
//----------------------------------------
ol.pushGeneratorState();
@@ -2674,6 +2704,13 @@ void MemberDef::writeDocumentation(MemberList *ml,
ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
ol.startMemberDoc(ciname,name(),memAnchor,title,memCount,memTotal,showInline);
+ if (!m_impl->metaData.isEmpty() && getLanguage()==SrcLangExt_Slice)
+ {
+ ol.startMemberDocPrefixItem();
+ ol.docify(m_impl->metaData);
+ ol.endMemberDocPrefixItem();
+ }
+
ClassDef *cd=getClassDef();
NamespaceDef *nd=getNamespaceDef();
if (!Config_getBool(HIDE_SCOPE_NAMES))
@@ -2778,6 +2815,21 @@ void MemberDef::writeDocumentation(MemberList *ml,
{
hasParameterList=VhdlDocGen::writeVHDLTypeDocumentation(this,scopedContainer,ol);
}
+ else if (lang==SrcLangExt_Slice)
+ {
+ // Eliminate the self-reference.
+ int pos = ldef.findRev(' ');
+ linkifyText(TextGeneratorOLImpl(ol),
+ scopedContainer,
+ getBodyDef(),
+ this,
+ ldef.left(pos)
+ );
+ ol.docify(ldef.mid(pos));
+ Definition *scope = cd;
+ if (scope==0) scope = nd;
+ hasParameterList=writeDefArgumentList(ol,scope,this);
+ }
else
{
linkifyText(TextGeneratorOLImpl(ol),
@@ -2984,9 +3036,9 @@ void MemberDef::writeDocumentation(MemberList *ml,
_writeExamples(ol);
_writeTypeConstraints(ol);
writeSourceDef(ol,cname);
- writeSourceRefs(ol,cname);
- writeSourceReffedBy(ol,cname);
writeInlineCode(ol,cname);
+ if (hasReferencesRelation()) writeSourceRefs(ol,cname);
+ if (hasReferencedByRelation()) writeSourceReffedBy(ol,cname);
_writeCallGraph(ol);
_writeCallerGraph(ol);
@@ -3082,7 +3134,7 @@ QCString MemberDef::fieldType() const
type = m_impl->type;
}
- if (isTypedef()) type.prepend("typedef ");
+ if (isTypedef() && getLanguage() != SrcLangExt_Slice) type.prepend("typedef ");
return simplifyTypeForTable(type);
}
@@ -3199,6 +3251,8 @@ QCString MemberDef::memberTypeName() const
case MemberType_Event: return "event";
case MemberType_Interface: return "interface";
case MemberType_Service: return "service";
+ case MemberType_Sequence: return "sequence";
+ case MemberType_Dictionary: return "dictionary";
default: return "unknown";
}
}
@@ -3461,7 +3515,7 @@ MemberDef *MemberDef::createTemplateInstanceMember(
methodName,
substituteTemplateArgumentsInString(m_impl->args,formalArgs,actualArgs),
m_impl->exception, m_impl->prot,
- m_impl->virt, m_impl->stat, m_impl->related, m_impl->mtype, 0, 0
+ m_impl->virt, m_impl->stat, m_impl->related, m_impl->mtype, 0, 0, ""
);
imd->setArgumentList(actualArgList);
imd->setDefinition(substituteTemplateArgumentsInString(m_impl->def,formalArgs,actualArgs));
@@ -3623,6 +3677,8 @@ void MemberDef::writeTagFile(FTextStream &tagFile)
case MemberType_Slot: tagFile << "slot"; break;
case MemberType_Interface: tagFile << "interface"; break;
case MemberType_Service: tagFile << "service"; break;
+ case MemberType_Sequence: tagFile << "sequence"; break;
+ case MemberType_Dictionary: tagFile << "dictionary"; break;
}
if (m_impl->prot!=Public)
{
@@ -3960,6 +4016,18 @@ void MemberDef::enableCallerGraph(bool e)
if (e) Doxygen::parseSourcesNeeded = TRUE;
}
+void MemberDef::enableReferencedByRelation(bool e)
+{
+ m_impl->hasReferencedByRelation=e;
+ if (e) Doxygen::parseSourcesNeeded = TRUE;
+}
+
+void MemberDef::enableReferencesRelation(bool e)
+{
+ m_impl->hasReferencesRelation=e;
+ if (e) Doxygen::parseSourcesNeeded = TRUE;
+}
+
#if 0
bool MemberDef::protectionVisible() const
{
@@ -4185,6 +4253,16 @@ bool MemberDef::isTypedef() const
return m_impl->mtype==MemberType_Typedef;
}
+bool MemberDef::isSequence() const
+{
+ return m_impl->mtype==MemberType_Sequence;
+}
+
+bool MemberDef::isDictionary() const
+{
+ return m_impl->mtype==MemberType_Dictionary;
+}
+
bool MemberDef::isFunction() const
{
return m_impl->mtype==MemberType_Function;
@@ -4522,6 +4600,11 @@ bool MemberDef::livesInsideEnum() const
return m_impl->livesInsideEnum;
}
+bool MemberDef::isSliceLocal() const
+{
+ return (m_impl->memSpec&Entry::Local)!=0;
+}
+
MemberList *MemberDef::enumFieldList() const
{
return m_impl->enumFields;
@@ -4592,6 +4675,16 @@ bool MemberDef::hasCallerGraph() const
return m_impl->hasCallerGraph;
}
+bool MemberDef::hasReferencedByRelation() const
+{
+ return m_impl->hasReferencedByRelation;
+}
+
+bool MemberDef::hasReferencesRelation() const
+{
+ return m_impl->hasReferencesRelation;
+}
+
MemberDef *MemberDef::templateMaster() const
{
return m_impl->templateMaster;
@@ -5104,6 +5197,11 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef)
mdef->enableCallerGraph(mdec->hasCallerGraph() || mdef->hasCallerGraph());
mdec->enableCallGraph(mdec->hasCallGraph() || mdef->hasCallGraph());
mdec->enableCallerGraph(mdec->hasCallerGraph() || mdef->hasCallerGraph());
+
+ mdef->enableReferencedByRelation(mdec->hasReferencedByRelation() || mdef->hasReferencedByRelation());
+ mdef->enableCallerGraph(mdec->hasReferencesRelation() || mdef->hasReferencesRelation());
+ mdec->enableReferencedByRelation(mdec->hasReferencedByRelation() || mdef->hasReferencedByRelation());
+ mdec->enableCallerGraph(mdec->hasReferencesRelation() || mdef->hasReferencesRelation());
}
}
}
diff --git a/src/memberdef.h b/src/memberdef.h
index bf7ea9a..2c88438 100644
--- a/src/memberdef.h
+++ b/src/memberdef.h
@@ -48,7 +48,7 @@ class MemberDef : public Definition
const char *type,const char *name,const char *args,
const char *excp,Protection prot,Specifier virt,bool stat,
Relationship related,MemberType t,const ArgumentList *tal,
- const ArgumentList *al);
+ const ArgumentList *al,const char *metaData);
~MemberDef();
DefType definitionType() const { return TypeMember; }
// move this member into a different scope
@@ -109,6 +109,8 @@ class MemberDef : public Definition
bool isEnumerate() const;
bool isEnumValue() const;
bool isTypedef() const;
+ bool isSequence() const;
+ bool isDictionary() const;
bool isFunction() const;
bool isFunctionPtr() const;
bool isDefine() const;
@@ -177,6 +179,7 @@ class MemberDef : public Definition
bool showInCallGraph() const;
bool isStrongEnumValue() const;
bool livesInsideEnum() const;
+ bool isSliceLocal() const;
int numberOfFlowKeyWords();
// derived getters
@@ -237,6 +240,9 @@ class MemberDef : public Definition
bool hasCallGraph() const;
bool hasCallerGraph() const;
bool visibleMemberGroup(bool hideNoHeader);
+ // refrenced related members
+ bool hasReferencesRelation() const;
+ bool hasReferencedByRelation() const;
MemberDef *templateMaster() const;
QCString getScopeString() const;
@@ -349,6 +355,9 @@ class MemberDef : public Definition
void enableCallGraph(bool e);
void enableCallerGraph(bool e);
+ void enableReferencedByRelation(bool e);
+ void enableReferencesRelation(bool e);
+
void setTemplateMaster(MemberDef *mt);
void addListReference(Definition *d);
void setDocsForDefinition(bool b);
diff --git a/src/membergroup.cpp b/src/membergroup.cpp
index aaa504f..5ee47ab 100644
--- a/src/membergroup.cpp
+++ b/src/membergroup.cpp
@@ -278,6 +278,16 @@ int MemberGroup::typedefCount() const
return memberList->typedefCount();
}
+int MemberGroup::sequenceCount() const
+{
+ return memberList->sequenceCount();
+}
+
+int MemberGroup::dictionaryCount() const
+{
+ return memberList->dictionaryCount();
+}
+
int MemberGroup::protoCount() const
{
return memberList->protoCount();
diff --git a/src/membergroup.h b/src/membergroup.h
index 29fba07..b590d48 100644
--- a/src/membergroup.h
+++ b/src/membergroup.h
@@ -76,6 +76,8 @@ class MemberGroup
int enumCount() const;
int enumValueCount() const;
int typedefCount() const;
+ int sequenceCount() const;
+ int dictionaryCount() const;
int protoCount() const;
int defineCount() const;
int friendCount() const;
diff --git a/src/memberlist.cpp b/src/memberlist.cpp
index e19cead..a4e5596 100644
--- a/src/memberlist.cpp
+++ b/src/memberlist.cpp
@@ -41,6 +41,8 @@ MemberList::MemberList() : m_listType(MemberListType_pubMethods)
m_enumCnt=0;
m_enumValCnt=0;
m_typeCnt=0;
+ m_seqCnt=0;
+ m_dictCnt=0;
m_protoCnt=0;
m_defCnt=0;
m_friendCnt=0;
@@ -59,6 +61,8 @@ MemberList::MemberList(MemberListType lt) : m_listType(lt)
m_enumCnt=0;
m_enumValCnt=0;
m_typeCnt=0;
+ m_seqCnt=0;
+ m_dictCnt=0;
m_protoCnt=0;
m_defCnt=0;
m_friendCnt=0;
@@ -139,7 +143,7 @@ void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd)
//printf("----- countDecMembers count=%d ----\n",count());
m_varCnt=m_funcCnt=m_enumCnt=m_enumValCnt=0;
- m_typeCnt=m_protoCnt=m_defCnt=m_friendCnt=0;
+ m_typeCnt=m_seqCnt=m_dictCnt=m_protoCnt=m_defCnt=m_friendCnt=0;
m_numDecMembers=0;
QListIterator<MemberDef> mli(*this);
MemberDef *md;
@@ -168,6 +172,8 @@ void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd)
m_enumValCnt++,m_numDecMembers++;
break;
case MemberType_Typedef: m_typeCnt++,m_numDecMembers++; break;
+ case MemberType_Sequence: m_seqCnt++,m_numDecMembers++; break;
+ case MemberType_Dictionary: m_dictCnt++,m_numDecMembers++; break;
//case MemberType_Prototype: m_protoCnt++,m_numDecMembers++; break;
case MemberType_Define: if (Config_getBool(EXTRACT_ALL) ||
md->argsString() ||
@@ -194,6 +200,8 @@ void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd)
m_enumCnt+=mg->enumCount();
m_enumValCnt+=mg->enumValueCount();
m_typeCnt+=mg->typedefCount();
+ m_seqCnt+=mg->sequenceCount();
+ m_dictCnt+=mg->dictionaryCount();
m_protoCnt+=mg->protoCount();
m_defCnt+=mg->defineCount();
m_friendCnt+=mg->friendCount();
@@ -314,16 +322,18 @@ bool MemberList::declVisible() const
{
switch (md->memberType())
{
- case MemberType_Define: // fall through
- case MemberType_Typedef: // fall through
- case MemberType_Variable: // fall through
- case MemberType_Function: // fall through
- case MemberType_Signal: // fall through
- case MemberType_Slot: // fall through
- case MemberType_DCOP: // fall through
- case MemberType_Property: // fall through
- case MemberType_Interface: // fall through
- case MemberType_Service: // fall through
+ case MemberType_Define: // fall through
+ case MemberType_Typedef: // fall through
+ case MemberType_Variable: // fall through
+ case MemberType_Function: // fall through
+ case MemberType_Signal: // fall through
+ case MemberType_Slot: // fall through
+ case MemberType_DCOP: // fall through
+ case MemberType_Property: // fall through
+ case MemberType_Interface: // fall through
+ case MemberType_Service: // fall through
+ case MemberType_Sequence: // fall through
+ case MemberType_Dictionary: // fall through
case MemberType_Event:
return TRUE;
case MemberType_Enumeration:
@@ -383,17 +393,19 @@ void MemberList::writePlainDeclarations(OutputList &ol,
//printf(">>> rendering\n");
switch(md->memberType())
{
- case MemberType_Define: // fall through
+ case MemberType_Define: // fall through
//case MemberType_Prototype: // fall through
- case MemberType_Typedef: // fall through
- case MemberType_Variable: // fall through
- case MemberType_Function: // fall through
- case MemberType_Signal: // fall through
- case MemberType_Slot: // fall through
- case MemberType_DCOP: // fall through
- case MemberType_Property: // fall through
- case MemberType_Interface: // fall through
- case MemberType_Service: // fall through
+ case MemberType_Typedef: // fall through
+ case MemberType_Variable: // fall through
+ case MemberType_Function: // fall through
+ case MemberType_Signal: // fall through
+ case MemberType_Slot: // fall through
+ case MemberType_DCOP: // fall through
+ case MemberType_Property: // fall through
+ case MemberType_Interface: // fall through
+ case MemberType_Service: // fall through
+ case MemberType_Sequence: // fall through
+ case MemberType_Dictionary: // fall through
case MemberType_Event:
{
if (first) ol.startMemberList(),first=FALSE;
@@ -419,6 +431,10 @@ void MemberList::writePlainDeclarations(OutputList &ol,
{
ol.startDoxyAnchor(md->getOutputFileBase(),0,md->anchor(),md->name(),QCString());
}
+ if (md->isSliceLocal())
+ {
+ ol.writeString("local ");
+ }
ol.writeString("enum ");
ol.insertMemberAlign();
md->writeEnumDeclaration(ol,cd,nd,fd,gd);
@@ -921,6 +937,8 @@ void MemberList::marshal(StorageIntf *s)
marshalInt(s,m_enumCnt);
marshalInt(s,m_enumValCnt);
marshalInt(s,m_typeCnt);
+ marshalInt(s,m_seqCnt);
+ marshalInt(s,m_dictCnt);
marshalInt(s,m_protoCnt);
marshalInt(s,m_defCnt);
marshalInt(s,m_friendCnt);
@@ -953,6 +971,8 @@ void MemberList::unmarshal(StorageIntf *s)
m_enumCnt = unmarshalInt(s);
m_enumValCnt = unmarshalInt(s);
m_typeCnt = unmarshalInt(s);
+ m_seqCnt = unmarshalInt(s);
+ m_dictCnt = unmarshalInt(s);
m_protoCnt = unmarshalInt(s);
m_defCnt = unmarshalInt(s);
m_friendCnt = unmarshalInt(s);
@@ -1021,6 +1041,8 @@ QCString MemberList::listTypeAsString(MemberListType type)
case MemberListType_decDefineMembers: return "define-members";
case MemberListType_decProtoMembers: return "proto-members";
case MemberListType_decTypedefMembers: return "typedef-members";
+ case MemberListType_decSequenceMembers: return "sequence-members";
+ case MemberListType_decDictionaryMembers: return "dictionary-members";
case MemberListType_decEnumMembers: return "enum-members";
case MemberListType_decFuncMembers: return "func-members";
case MemberListType_decVarMembers: return "var-members";
diff --git a/src/memberlist.h b/src/memberlist.h
index 38f0e89..a96f61f 100644
--- a/src/memberlist.h
+++ b/src/memberlist.h
@@ -50,17 +50,19 @@ class MemberList : private QList<MemberDef>
MemberDef *take(uint index);
- int varCount() const { ASSERT(m_numDecMembers!=-1); return m_varCnt; }
- int funcCount() const { ASSERT(m_numDecMembers!=-1); return m_funcCnt; }
- int enumCount() const { ASSERT(m_numDecMembers!=-1); return m_enumCnt; }
- int enumValueCount() const { ASSERT(m_numDecMembers!=-1); return m_enumValCnt; }
- int typedefCount() const { ASSERT(m_numDecMembers!=-1); return m_typeCnt; }
- int protoCount() const { ASSERT(m_numDecMembers!=-1); return m_protoCnt; }
- int defineCount() const { ASSERT(m_numDecMembers!=-1); return m_defCnt; }
- int friendCount() const { ASSERT(m_numDecMembers!=-1); return m_friendCnt; }
- int numDecMembers() const { ASSERT(m_numDecMembers!=-1); return m_numDecMembers; }
- int numDocMembers() const { ASSERT(m_numDocMembers!=-1); return m_numDocMembers; }
- bool needsSorting() const { return m_needsSorting; }
+ int varCount() const { ASSERT(m_numDecMembers!=-1); return m_varCnt; }
+ int funcCount() const { ASSERT(m_numDecMembers!=-1); return m_funcCnt; }
+ int enumCount() const { ASSERT(m_numDecMembers!=-1); return m_enumCnt; }
+ int enumValueCount() const { ASSERT(m_numDecMembers!=-1); return m_enumValCnt; }
+ int typedefCount() const { ASSERT(m_numDecMembers!=-1); return m_typeCnt; }
+ int sequenceCount() const { ASSERT(m_numDecMembers!=-1); return m_seqCnt; }
+ int dictionaryCount() const { ASSERT(m_numDecMembers!=-1); return m_dictCnt; }
+ int protoCount() const { ASSERT(m_numDecMembers!=-1); return m_protoCnt; }
+ int defineCount() const { ASSERT(m_numDecMembers!=-1); return m_defCnt; }
+ int friendCount() const { ASSERT(m_numDecMembers!=-1); return m_friendCnt; }
+ int numDecMembers() const { ASSERT(m_numDecMembers!=-1); return m_numDecMembers; }
+ int numDocMembers() const { ASSERT(m_numDocMembers!=-1); return m_numDocMembers; }
+ bool needsSorting() const { return m_needsSorting; }
void countDecMembers(bool countEnumValues=FALSE,GroupDef *gd=0);
void countDocMembers(bool countEnumValues=FALSE);
int countInheritableMembers(ClassDef *inheritedFrom) const;
@@ -98,6 +100,8 @@ class MemberList : private QList<MemberDef>
int m_enumCnt;
int m_enumValCnt;
int m_typeCnt;
+ int m_seqCnt;
+ int m_dictCnt;
int m_protoCnt;
int m_defCnt;
int m_friendCnt;
diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp
index 8e6c881..bc8bb47 100644
--- a/src/namespacedef.cpp
+++ b/src/namespacedef.cpp
@@ -56,6 +56,9 @@ NamespaceDef::NamespaceDef(const char *df,int dl,int dc,
setFileName(name);
}
classSDict = new ClassSDict(17);
+ interfaceSDict = new ClassSDict(17);
+ structSDict = new ClassSDict(17);
+ exceptionSDict = new ClassSDict(17);
namespaceSDict = new NamespaceSDict(17);
m_innerCompounds = new SDict<Definition>(17);
usingDirList = 0;
@@ -87,6 +90,9 @@ NamespaceDef::NamespaceDef(const char *df,int dl,int dc,
NamespaceDef::~NamespaceDef()
{
delete classSDict;
+ delete interfaceSDict;
+ delete structSDict;
+ delete exceptionSDict;
delete namespaceSDict;
delete m_innerCompounds;
delete usingDirList;
@@ -164,12 +170,34 @@ void NamespaceDef::addInnerCompound(Definition *d)
void NamespaceDef::insertClass(ClassDef *cd)
{
- if (classSDict->find(cd->name())==0)
+ ClassSDict *d = classSDict;
+
+ if (Config_getBool(OPTIMIZE_OUTPUT_SLICE))
+ {
+ if (cd->compoundType()==ClassDef::Interface)
+ {
+ d = interfaceSDict;
+ }
+ else if (cd->compoundType()==ClassDef::Struct)
+ {
+ d = structSDict;
+ }
+ else if (cd->compoundType()==ClassDef::Exception)
+ {
+ d = exceptionSDict;
+ }
+ }
+
+ if (d->find(cd->name())==0)
{
if (Config_getBool(SORT_BRIEF_DOCS))
- classSDict->inSort(cd->name(),cd);
+ {
+ d->inSort(cd->name(),cd);
+ }
else
- classSDict->append(cd->name(),cd);
+ {
+ d->append(cd->name(),cd);
+ }
}
}
@@ -245,6 +273,14 @@ void NamespaceDef::insertMember(MemberDef *md)
addMemberToList(MemberListType_decTypedefMembers,md);
addMemberToList(MemberListType_docTypedefMembers,md);
break;
+ case MemberType_Sequence:
+ addMemberToList(MemberListType_decSequenceMembers,md);
+ addMemberToList(MemberListType_docSequenceMembers,md);
+ break;
+ case MemberType_Dictionary:
+ addMemberToList(MemberListType_decDictionaryMembers,md);
+ addMemberToList(MemberListType_docDictionaryMembers,md);
+ break;
case MemberType_Enumeration:
addMemberToList(MemberListType_decEnumMembers,md);
addMemberToList(MemberListType_docEnumMembers,md);
@@ -313,18 +349,25 @@ void NamespaceDef::writeTagFile(FTextStream &tagFile)
case LayoutDocEntry::NamespaceClasses:
{
if (classSDict)
- {
- SDict<ClassDef>::Iterator ci(*classSDict);
- ClassDef *cd;
- for (ci.toFirst();(cd=ci.current());++ci)
- {
- if (cd->isLinkableInProject())
- {
- tagFile << " <class kind=\"" << cd->compoundTypeString()
- << "\">" << convertToXML(cd->name()) << "</class>" << endl;
- }
- }
- }
+ writeClassesToTagFile(tagFile, classSDict);
+ }
+ break;
+ case LayoutDocEntry::NamespaceInterfaces:
+ {
+ if (interfaceSDict)
+ writeClassesToTagFile(tagFile, interfaceSDict);
+ }
+ break;
+ case LayoutDocEntry::NamespaceStructs:
+ {
+ if (structSDict)
+ writeClassesToTagFile(tagFile, structSDict);
+ }
+ break;
+ case LayoutDocEntry::NamespaceExceptions:
+ {
+ if (exceptionSDict)
+ writeClassesToTagFile(tagFile, exceptionSDict);
}
break;
case LayoutDocEntry::MemberDecl:
@@ -437,6 +480,24 @@ void NamespaceDef::writeBriefDescription(OutputList &ol)
//ol.newParagraph();
//ol.popGeneratorState();
}
+
+ // Write a summary of the Slice definition including metadata.
+ if (getLanguage() == SrcLangExt_Slice)
+ {
+ ol.startParagraph();
+ ol.startTypewriter();
+ if (!metaData.isEmpty())
+ {
+ ol.docify(metaData);
+ ol.lineBreak();
+ }
+ ol.docify("module ");
+ ol.docify(stripScope(name()));
+ ol.docify(" { ... }");
+ ol.endTypewriter();
+ ol.endParagraph();
+ }
+
ol.writeSynopsis();
}
@@ -468,9 +529,9 @@ void NamespaceDef::endMemberDocumentation(OutputList &ol)
}
}
-void NamespaceDef::writeClassDeclarations(OutputList &ol,const QCString &title)
+void NamespaceDef::writeClassDeclarations(OutputList &ol,const QCString &title,ClassSDict *d)
{
- if (classSDict) classSDict->writeDeclaration(ol,0,title,TRUE);
+ if (d) d->writeDeclaration(ol,0,title,TRUE);
}
void NamespaceDef::writeInlineClasses(OutputList &ol)
@@ -526,12 +587,38 @@ void NamespaceDef::writeSummaryLinks(OutputList &ol)
SrcLangExt lang = getLanguage();
for (eli.toFirst();(lde=eli.current());++eli)
{
- if ((lde->kind()==LayoutDocEntry::NamespaceClasses && classSDict && classSDict->declVisible()) ||
- (lde->kind()==LayoutDocEntry::NamespaceNestedNamespaces && namespaceSDict && namespaceSDict->declVisible())
- )
+ if (lde->kind()==LayoutDocEntry::NamespaceClasses && classSDict && classSDict->declVisible())
{
LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
- QCString label = lde->kind()==LayoutDocEntry::NamespaceClasses ? "nested-classes" : "namespaces";
+ QCString label = "nested-classes";
+ ol.writeSummaryLink(0,label,ls->title(lang),first);
+ first=FALSE;
+ }
+ else if (lde->kind()==LayoutDocEntry::NamespaceInterfaces && interfaceSDict && interfaceSDict->declVisible())
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ QCString label = "interfaces";
+ ol.writeSummaryLink(0,label,ls->title(lang),first);
+ first=FALSE;
+ }
+ else if (lde->kind()==LayoutDocEntry::NamespaceStructs && structSDict && structSDict->declVisible())
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ QCString label = "structs";
+ ol.writeSummaryLink(0,label,ls->title(lang),first);
+ first=FALSE;
+ }
+ else if (lde->kind()==LayoutDocEntry::NamespaceExceptions && exceptionSDict && exceptionSDict->declVisible())
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ QCString label = "exceptions";
+ ol.writeSummaryLink(0,label,ls->title(lang),first);
+ first=FALSE;
+ }
+ else if (lde->kind()==LayoutDocEntry::NamespaceNestedNamespaces && namespaceSDict && namespaceSDict->declVisible())
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ QCString label = "namespaces";
ol.writeSummaryLink(0,label,ls->title(lang),first);
first=FALSE;
}
@@ -567,6 +654,20 @@ void NamespaceDef::addNamespaceAttributes(OutputList &ol)
}
}
+void NamespaceDef::writeClassesToTagFile(FTextStream &tagFile,ClassSDict *d)
+{
+ SDict<ClassDef>::Iterator ci(*d);
+ ClassDef *cd;
+ for (ci.toFirst();(cd=ci.current());++ci)
+ {
+ if (cd->isLinkableInProject())
+ {
+ tagFile << " <class kind=\"" << cd->compoundTypeString()
+ << "\">" << convertToXML(cd->name()) << "</class>" << endl;
+ }
+ }
+}
+
void NamespaceDef::writeDocumentation(OutputList &ol)
{
static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
@@ -619,7 +720,25 @@ void NamespaceDef::writeDocumentation(OutputList &ol)
case LayoutDocEntry::NamespaceClasses:
{
LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
- writeClassDeclarations(ol,ls->title(lang));
+ writeClassDeclarations(ol,ls->title(lang),classSDict);
+ }
+ break;
+ case LayoutDocEntry::NamespaceInterfaces:
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ writeClassDeclarations(ol,ls->title(lang),interfaceSDict);
+ }
+ break;
+ case LayoutDocEntry::NamespaceStructs:
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ writeClassDeclarations(ol,ls->title(lang),structSDict);
+ }
+ break;
+ case LayoutDocEntry::NamespaceExceptions:
+ {
+ LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
+ writeClassDeclarations(ol,ls->title(lang),exceptionSDict);
}
break;
case LayoutDocEntry::NamespaceNestedNamespaces:
@@ -678,6 +797,9 @@ void NamespaceDef::writeDocumentation(OutputList &ol)
case LayoutDocEntry::ClassUsedFiles:
case LayoutDocEntry::ClassInlineClasses:
case LayoutDocEntry::FileClasses:
+ case LayoutDocEntry::FileInterfaces:
+ case LayoutDocEntry::FileStructs:
+ case LayoutDocEntry::FileExceptions:
case LayoutDocEntry::FileNamespaces:
case LayoutDocEntry::FileConstantGroups:
case LayoutDocEntry::FileIncludes:
@@ -780,7 +902,8 @@ int NamespaceDef::countMembers()
{
MemberList *allMemberList = getMemberList(MemberListType_allMembersList);
if (allMemberList) allMemberList->countDocMembers();
- return (allMemberList ? allMemberList->numDocMembers() : 0)+classSDict->count();
+ return (allMemberList ? allMemberList->numDocMembers() : 0) +
+ classSDict->count() + interfaceSDict->count() + structSDict->count() + exceptionSDict->count();
}
void NamespaceDef::addUsingDirective(NamespaceDef *nd)
@@ -1079,14 +1202,24 @@ void NamespaceDef::sortMemberLists()
{
classSDict->sort();
}
+ if (interfaceSDict)
+ {
+ interfaceSDict->sort();
+ }
+ if (structSDict)
+ {
+ structSDict->sort();
+ }
+ if (exceptionSDict)
+ {
+ exceptionSDict->sort();
+ }
if (namespaceSDict)
{
namespaceSDict->sort();
}
}
-
-
MemberList *NamespaceDef::getMemberList(MemberListType lt) const
{
QListIterator<MemberList> mli(m_memberLists);
@@ -1156,7 +1289,7 @@ QCString NamespaceDef::title() const
{
pageTitle = theTranslator->trPackage(displayName());
}
- else if (lang==SrcLangExt_Fortran)
+ else if (lang==SrcLangExt_Fortran || lang==SrcLangExt_Slice)
{
pageTitle = theTranslator->trModuleReference(displayName());
}
@@ -1210,3 +1343,7 @@ QCString NamespaceDef::compoundTypeString() const
return "";
}
+void NamespaceDef::setMetaData(const QCString &m)
+{
+ metaData = m;
+}
diff --git a/src/namespacedef.h b/src/namespacedef.h
index 8b7d7cc..b46d074 100644
--- a/src/namespacedef.h
+++ b/src/namespacedef.h
@@ -97,12 +97,23 @@ class NamespaceDef : public Definition
/*! Returns the classes contained in this namespace */
ClassSDict *getClassSDict() const { return classSDict; }
+ /*! Returns the Slice interfaces contained in this namespace */
+ ClassSDict *getInterfaceSDict() const { return interfaceSDict; }
+
+ /*! Returns the Slice structs contained in this namespace */
+ ClassSDict *getStructSDict() const { return structSDict; }
+
+ /*! Returns the Slice exceptions contained in this namespace */
+ ClassSDict *getExceptionSDict() const { return exceptionSDict; }
+
/*! Returns the namespaces contained in this namespace */
NamespaceSDict *getNamespaceSDict() const { return namespaceSDict; }
QCString title() const;
QCString compoundTypeString() const;
+ void setMetaData(const QCString &m);
+
bool visited;
private:
@@ -114,7 +125,7 @@ class NamespaceDef : public Definition
void writeBriefDescription(OutputList &ol);
void startMemberDeclarations(OutputList &ol);
void endMemberDeclarations(OutputList &ol);
- void writeClassDeclarations(OutputList &ol,const QCString &title);
+ void writeClassDeclarations(OutputList &ol,const QCString &title,ClassSDict *d);
void writeInlineClasses(OutputList &ol);
void writeNamespaceDeclarations(OutputList &ol,const QCString &title,
bool isConstantGroup=false);
@@ -124,6 +135,7 @@ class NamespaceDef : public Definition
void endMemberDocumentation(OutputList &ol);
void writeSummaryLinks(OutputList &ol);
void addNamespaceAttributes(OutputList &ol);
+ void writeClassesToTagFile(FTextStream &,ClassSDict *d);
QCString fileName;
FileList files;
@@ -136,10 +148,14 @@ class NamespaceDef : public Definition
QList<MemberList> m_memberLists;
MemberGroupSDict *memberGroupSDict;
ClassSDict *classSDict;
+ ClassSDict *interfaceSDict;
+ ClassSDict *structSDict;
+ ClassSDict *exceptionSDict;
NamespaceSDict *namespaceSDict;
bool m_subGrouping;
enum { NAMESPACE, MODULE, CONSTANT_GROUP, LIBRARY } m_type;
bool m_isPublished;
+ QCString metaData;
};
/** A list of NamespaceDef objects. */
diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp
index 5b4b6ea..044efff 100644
--- a/src/perlmodgen.cpp
+++ b/src/perlmodgen.cpp
@@ -43,6 +43,7 @@
#include "section.h"
#include "util.h"
#include "htmlentity.h"
+#include "emoji.h"
#define PERLOUTPUT_MAX_INDENTATION 40
@@ -299,6 +300,7 @@ public:
void visit(DocLinkedWord *);
void visit(DocWhiteSpace *);
void visit(DocSymbol *);
+ void visit(DocEmoji *);
void visit(DocURL *);
void visit(DocLineBreak *);
void visit(DocHorRuler *);
@@ -609,6 +611,11 @@ void PerlModDocVisitor::visit(DocSymbol *sy)
err("perl: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(sy->symbol(),TRUE));
}
}
+void PerlModDocVisitor::visit(DocEmoji *sy)
+{
+ enterText();
+ m_output.add(EmojiEntityMapper::instance()->perl(sy->emoji()));
+}
void PerlModDocVisitor::visit(DocURL *u)
{
@@ -1570,21 +1577,22 @@ void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *)
bool isFunc=FALSE;
switch (md->memberType())
{
- case MemberType_Define: memType="define"; break;
- case MemberType_EnumValue: memType="enumvalue"; break;
- case MemberType_Property: memType="property"; break;
- case MemberType_Variable: memType="variable"; break;
- case MemberType_Typedef: memType="typedef"; break;
- case MemberType_Enumeration: memType="enum"; break;
- case MemberType_Function: memType="function"; isFunc=TRUE; break;
- case MemberType_Signal: memType="signal"; isFunc=TRUE; break;
- //case MemberType_Prototype: memType="prototype"; isFunc=TRUE; break;
- case MemberType_Friend: memType="friend"; isFunc=TRUE; break;
- case MemberType_DCOP: memType="dcop"; isFunc=TRUE; break;
- case MemberType_Slot: memType="slot"; isFunc=TRUE; break;
- case MemberType_Event: memType="event"; break;
- case MemberType_Interface: memType="interface"; break;
- case MemberType_Service: memType="service"; break;
+ case MemberType_Define: memType="define"; break;
+ case MemberType_EnumValue: memType="enumvalue"; break;
+ case MemberType_Property: memType="property"; break;
+ case MemberType_Variable: memType="variable"; break;
+ case MemberType_Typedef: memType="typedef"; break;
+ case MemberType_Enumeration: memType="enum"; break;
+ case MemberType_Function: memType="function"; isFunc=TRUE; break;
+ case MemberType_Signal: memType="signal"; isFunc=TRUE; break;
+ case MemberType_Friend: memType="friend"; isFunc=TRUE; break;
+ case MemberType_DCOP: memType="dcop"; isFunc=TRUE; break;
+ case MemberType_Slot: memType="slot"; isFunc=TRUE; break;
+ case MemberType_Event: memType="event"; break;
+ case MemberType_Interface: memType="interface"; break;
+ case MemberType_Service: memType="service"; break;
+ case MemberType_Sequence: memType="sequence"; break;
+ case MemberType_Dictionary: memType="dictionary"; break;
}
m_output.openHash()
@@ -1609,7 +1617,7 @@ void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *)
m_output.openList("parameters");
ArgumentList *declAl = md->declArgumentList();
ArgumentList *defAl = md->argumentList();
- if (declAl && declAl->count()>0)
+ if (declAl && defAl && declAl->count()>0)
{
ArgumentListIterator declAli(*declAl);
ArgumentListIterator defAli(*defAl);
diff --git a/src/portable.cpp b/src/portable.cpp
index 08691b2..3dccaed 100644
--- a/src/portable.cpp
+++ b/src/portable.cpp
@@ -211,8 +211,8 @@ void portable_setenv(const char *name,const char *value)
#if defined(_WIN32) && !defined(__CYGWIN__)
SetEnvironmentVariable(name,value);
#else
- register char **ep = 0;
- register size_t size;
+ char **ep = 0;
+ size_t size;
const size_t namelen=qstrlen(name);
const size_t vallen=qstrlen(value) + 1;
diff --git a/src/pre.l b/src/pre.l
index b6ebbf8..5eb0c5c 100644
--- a/src/pre.l
+++ b/src/pre.l
@@ -1405,7 +1405,7 @@ void addDefine()
MemberDef *md=new MemberDef(
g_yyFileName,g_yyLineNr-g_yyMLines,g_yyColNr,
"#define",g_defName,g_defArgsStr,0,
- Public,Normal,FALSE,Member,MemberType_Define,0,0);
+ Public,Normal,FALSE,Member,MemberType_Define,0,0,"");
if (!g_defArgsStr.isEmpty())
{
ArgumentList *argList = new ArgumentList;
diff --git a/src/printdocvisitor.h b/src/printdocvisitor.h
index 8d9a2b9..17d938e 100644
--- a/src/printdocvisitor.h
+++ b/src/printdocvisitor.h
@@ -22,6 +22,7 @@
#include <qglobal.h>
#include "docvisitor.h"
#include "htmlentity.h"
+#include "emoji.h"
#include "message.h"
/*! Concrete visitor implementation for pretty printing */
@@ -68,6 +69,19 @@ class PrintDocVisitor : public DocVisitor
printf("print: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s->symbol(),TRUE));
}
}
+ void visit(DocEmoji *s)
+ {
+ indent_leaf();
+ const char *res = EmojiEntityMapper::instance()->utf8(s->emoji());
+ if (res)
+ {
+ printf("%s",res);
+ }
+ else
+ {
+ printf("print: non supported Emoji-entity found: %s\n",EmojiEntityMapper::instance()->html(s->emoji()));
+ }
+ }
void visit(DocURL *u)
{
indent_leaf();
@@ -496,7 +510,7 @@ class PrintDocVisitor : public DocVisitor
case DocImage::Rtf: printf("rtf"); break;
case DocImage::DocBook: printf("docbook"); break;
}
- printf("\" %s %s>\n",img->width().data(),img->height().data());
+ printf("\" %s %s inline=\"%s\">\n",img->width().data(),img->height().data(),img->isInlineImage() ? "yes" : "no");
}
void visitPost(DocImage *)
{
@@ -640,13 +654,13 @@ class PrintDocVisitor : public DocVisitor
void visitPre(DocXRefItem *x)
{
indent_pre();
- printf("<xrefitem file=\"%s\" anchor=\"%s\" title=\"%s\"/>\n",
+ printf("<xrefitem file=\"%s\" anchor=\"%s\" title=\"%s\">\n",
x->file().data(),x->anchor().data(),x->title().data());
}
void visitPost(DocXRefItem *)
{
indent_post();
- printf("<xrefitem/>\n");
+ printf("</xrefitem>\n");
}
void visitPre(DocInternalRef *r)
{
diff --git a/src/pyscanner.l b/src/pyscanner.l
index 3743712..aed1ede 100644
--- a/src/pyscanner.l
+++ b/src/pyscanner.l
@@ -119,6 +119,7 @@ static bool g_start_init = FALSE;
static int g_search_count = 0;
static QCString g_argType = "";
+static bool g_funcParamsEnd;
//-----------------------------------------------------------------------------
@@ -514,6 +515,8 @@ STARTDOCSYMS "##"
%x FunctionDec
%x FunctionParams
%x FunctionBody
+%x FunctionAnnotation
+%x FunctionTypeAnnotation
%x FunctionParamDefVal
/* Class states */
@@ -933,7 +936,6 @@ STARTDOCSYMS "##"
}
<FunctionDec>{
-
{IDENTIFIER} {
//found function name
if (current->type.isEmpty())
@@ -944,16 +946,26 @@ STARTDOCSYMS "##"
current->name = current->name.stripWhiteSpace();
newFunction();
}
- {B}":" { // function without arguments
+ {B}":"{B} { // function without arguments
g_specialBlock = TRUE; // expecting a docstring
bodyEntry = current;
current->bodyLine = yyLineNr;
- BEGIN( FunctionBody );
+ BEGIN(FunctionBody);
}
+ "->" {
+ g_defVal.resize(0);
+ g_braceCount = 0;
+ BEGIN(FunctionTypeAnnotation);
+ }
{B}"(" {
- BEGIN( FunctionParams );
+ g_funcParamsEnd = FALSE;
+ BEGIN(FunctionParams);
}
+ ")" { // end of parameter list
+ current->args = argListToString(current->argList);
+ g_funcParamsEnd = TRUE;
+ }
}
<FunctionParams>{
@@ -975,20 +987,18 @@ STARTDOCSYMS "##"
// TODO: this rule is too simple, need to be able to
// match things like =")" as well!
g_defVal.resize(0);
- g_braceCount=0;
+ g_braceCount = 0;
BEGIN(FunctionParamDefVal);
}
-
- ")" { // end of parameter list
- current->args = argListToString(current->argList);
+ ")" {
+ unput(*yytext);
+ BEGIN(FunctionDec);
}
-
":"{B} {
- g_specialBlock = TRUE; // expecting a docstring
- bodyEntry = current;
- current->bodyLine = yyLineNr;
- BEGIN( FunctionBody );
- }
+ g_defVal.resize(0);
+ g_braceCount = 0;
+ BEGIN(FunctionAnnotation);
+ }
{POUNDCOMMENT} { // a comment
}
{PARAMNONEMPTY} { // Default rule inside arguments.
@@ -996,31 +1006,131 @@ STARTDOCSYMS "##"
}
+<FunctionTypeAnnotation>{
+ "{" |
+ "[" |
+ "(" {
+ ++g_braceCount;
+ g_defVal+=*yytext;
+ }
+ "}" |
+ "]" |
+ ")" {
+ --g_braceCount;
+ g_defVal+=*yytext;
+ }
+ ":" {
+ if (g_braceCount == 0)
+ {
+ current->type = g_defVal.data();
+ unput(*yytext);
+ BEGIN(FunctionDec);
+ }
+ else
+ g_defVal+=*yytext;
+ }
+ "'" {
+ g_defVal+=*yytext;
+ g_copyString=&g_defVal;
+ g_stringContext=FunctionTypeAnnotation;
+ BEGIN(SingleQuoteString);
+ }
+ "\"" {
+ g_defVal+=*yytext;
+ g_copyString=&g_defVal;
+ g_stringContext=FunctionTypeAnnotation;
+ BEGIN(DoubleQuoteString);
+ }
+ \n {
+ g_defVal+=*yytext;
+ incLineNr();
+ }
+ . {
+ g_defVal+=*yytext;
+ }
+}
+
+<FunctionAnnotation>{
+ "{" |
+ "[" |
+ "(" {
+ ++g_braceCount;
+ g_defVal+=*yytext;
+ }
+ "}" |
+ "]" {
+ --g_braceCount;
+ g_defVal+=*yytext;
+ }
+ ")" |
+ "=" |
+ "," {
+ if (g_braceCount == 0)
+ {
+ if (current->argList->getLast())
+ current->argList->getLast()->type += g_defVal.data();
+ if (*yytext != ',')
+ unput(*yytext);
+ BEGIN(FunctionParams);
+ }
+ else
+ {
+ if (*yytext == ')')
+ --g_braceCount;
+ g_defVal += *yytext;
+ }
+ }
+ "'" {
+ g_defVal+=*yytext;
+ g_copyString=&g_defVal;
+ g_stringContext=FunctionAnnotation;
+ BEGIN(SingleQuoteString);
+ }
+ "\"" {
+ g_defVal+=*yytext;
+ g_copyString=&g_defVal;
+ g_stringContext=FunctionAnnotation;
+ BEGIN(DoubleQuoteString);
+ }
+ \n {
+ g_defVal+=*yytext;
+ incLineNr();
+ }
+ . {
+ g_defVal+=*yytext;
+ }
+}
+
<FunctionParamDefVal>{
+ "{" |
"[" |
"(" { // internal opening brace, assumption is that we have correct code so braces do match
- g_braceCount++;
+ ++g_braceCount;
g_defVal+=*yytext;
}
- "," |
- "]" |
- ")" {
- if (g_braceCount==0) // end of default argument
+ "}" |
+ "]" {
+ --g_braceCount;
+ g_defVal+=*yytext;
+ }
+ ")" |
+ "," {
+ if (g_braceCount == 0)
{
if (current->argList->getLast())
- {
current->argList->getLast()->defval=QCString(g_defVal.data()).stripWhiteSpace();
- }
- if (*yytext != ',')
- current->args = argListToString(current->argList);
+ if (*yytext == ')')
+ unput(*yytext);
BEGIN(FunctionParams);
}
- else // continue
- {
- if (*yytext != ',')g_braceCount--;
- g_defVal+=*yytext;
- }
+ else
+ {
+ if (*yytext == ')')
+ --g_braceCount;
+ g_defVal += *yytext;
+ }
}
+
"'" {
g_defVal+=*yytext;
g_copyString=&g_defVal;
diff --git a/src/reflist.cpp b/src/reflist.cpp
index 1da603e..6f2a763 100644
--- a/src/reflist.cpp
+++ b/src/reflist.cpp
@@ -131,7 +131,15 @@ void RefList::insertIntoList(const char *key,RefItem *item)
{
if (ri!=item)
{
- ri->extraItems.append(item);
+ // We also have to check if the item is not already in the "extra" list
+ QListIterator<RefItem> li(ri->extraItems);
+ RefItem *extraItem;
+ bool doubleItem = false;
+ for (li.toFirst();(extraItem=li.current());++li)
+ {
+ if (item == extraItem) doubleItem = true;
+ }
+ if (!doubleItem) ri->extraItems.append(item);
}
}
}
@@ -148,8 +156,6 @@ void RefList::generatePage()
for (it.toFirst();(item=it.current());++it)
{
doc += " <dt>";
- doc += "\\anchor ";
- doc += item->listAnchor;
doc += "\n";
if (item->scope)
{
@@ -163,23 +169,38 @@ void RefList::generatePage()
doc += item->prefix;
doc += " \\_internalref ";
doc += item->name;
- doc += " \"";
// escape \'s in title, see issue #5901
- doc += substitute(item->title,"\\","\\\\");
- doc += "\" ";
+ QCString escapedTitle = substitute(item->title,"\\","\\\\");
+ if (item->scope &&
+ (item->scope->definitionType()==Definition::TypeClass ||
+ item->scope->definitionType()==Definition::TypeNamespace ||
+ item->scope->definitionType()==Definition::TypeMember ||
+ item->scope->definitionType()==Definition::TypePackage)
+ )
+ {
+ // prevent Obj-C names in e.g. todo list are seen as emoji
+ escapedTitle = substitute(escapedTitle,":","&Colon;");
+ }
+ doc += " \""+escapedTitle+"\" ";
// write declaration in case a function with arguments
if (!item->args.isEmpty())
{
// escape @'s in argument list, needed for Java annotations (see issue #6208)
- doc += substitute(item->args,"@","@@");
+ // escape \'s in argument list (see issue #6533)
+ doc += substitute(substitute(item->args,"@","@@"),"\\","\\\\");
}
- doc += "</dt><dd> ";
+ doc += "</dt><dd> \\anchor ";
+ doc += item->listAnchor;
+ doc += " ";
doc += item->text;
QListIterator<RefItem> li(item->extraItems);
RefItem *extraItem;
for (li.toFirst();(extraItem=li.current());++li)
{
- doc += "<p>" + extraItem->text;
+ doc += "<p> \\anchor ";
+ doc += extraItem->listAnchor;
+ doc += " ";
+ doc += extraItem->text;
}
doc += "</dd>";
}
diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp
index 7fbfdc8..658950a 100644
--- a/src/rtfdocvisitor.cpp
+++ b/src/rtfdocvisitor.cpp
@@ -34,6 +34,7 @@
#include "filedef.h"
#include "config.h"
#include "htmlentity.h"
+#include "emoji.h"
#include "plantuml.h"
//#define DBG_RTF(x) m_t << x
@@ -136,6 +137,48 @@ void RTFDocVisitor::visit(DocSymbol *s)
m_lastIsPara=FALSE;
}
+void RTFDocVisitor::visit(DocEmoji *s)
+{
+ if (m_hide) return;
+ DBG_RTF("{\\comment RTFDocVisitor::visit(DocEmoji)}\n");
+ const char *res = EmojiEntityMapper::instance()->rtf(s->emoji());
+ if (res)
+ {
+ const char *p = res;
+ int val = 0;
+ int val1 = 0;
+ while (*p)
+ {
+ switch(*p)
+ {
+ case '&': case '#': case 'x':
+ break;
+ case ';':
+ val1 = val;
+ val = 0xd800 + ( ( val1 - 0x10000 ) & 0xffc00 ) / 0x400 - 0x10000;
+ m_t << "\\u" << val << "?";
+ val = 0xdC00 + ( ( val1 - 0x10000 ) & 0x3ff ) - 0x10000 ;
+ m_t << "\\u" << val << "?";
+ val = 0;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ val = val * 16 + *p - '0';
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ val = val * 16 + *p - 'a' + 10;
+ break;
+ }
+ p++;
+ }
+ }
+ else
+ {
+ err("RTF: non supported Emoji-entity found: %s\n",EmojiEntityMapper::instance()->html(s->emoji()));
+ }
+ m_lastIsPara=FALSE;
+}
+
void RTFDocVisitor::visit(DocURL *u)
{
if (m_hide) return;
@@ -1072,7 +1115,7 @@ void RTFDocVisitor::visitPre(DocHtmlHeader *header)
m_t << "{" // start section
<< rtf_Style_Reset;
QCString heading;
- int level = QMIN(header->level()+2,4);
+ int level = QMIN(header->level(),5);
heading.sprintf("Heading%d",level);
// set style
m_t << rtf_Style[heading]->reference;
@@ -1094,27 +1137,37 @@ void RTFDocVisitor::visitPost(DocHtmlHeader *)
void RTFDocVisitor::visitPre(DocImage *img)
{
DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocImage)}\n");
- includePicturePreRTF(img->name(), img->type()==DocImage::Rtf, img->hasCaption());
+ includePicturePreRTF(img->name(), img->type()==DocImage::Rtf, img->hasCaption(), img->isInlineImage());
}
-
-void RTFDocVisitor::includePicturePreRTF(const QCString name, const bool isTypeRTF, const bool hasCaption)
+void RTFDocVisitor::includePicturePreRTF(const QCString name, bool isTypeRTF, bool hasCaption, bool inlineImage)
{
if (isTypeRTF)
{
- m_t << "\\par" << endl;
- m_t << "{" << endl;
- m_t << rtf_Style_Reset << endl;
- if (hasCaption || m_lastIsPara) m_t << "\\par" << endl;
- m_t << "\\pard \\qc { \\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
+ if (!inlineImage)
+ {
+ m_t << "\\par" << endl;
+ m_t << "{" << endl;
+ m_t << rtf_Style_Reset << endl;
+ if (hasCaption || m_lastIsPara) m_t << "\\par" << endl;
+ m_t << "\\pard \\qc ";
+ }
+ m_t << "{ \\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
m_t << name;
m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt Image}}" << endl;
- m_t << "\\par" << endl;
- if (hasCaption)
+ if (!inlineImage)
+ {
+ m_t << "\\par" << endl;
+ if (hasCaption)
+ {
+ m_t << "\\pard \\qc \\b";
+ m_t << "{Image \\field\\flddirty{\\*\\fldinst { SEQ Image \\\\*Arabic }}{\\fldrslt {\\noproof 1}} ";
+ }
+ m_lastIsPara=TRUE;
+ }
+ else
{
- m_t << "\\pard \\qc \\b";
- m_t << "{Image \\field\\flddirty{\\*\\fldinst { SEQ Image \\\\*Arabic }}{\\fldrslt {\\noproof 1}} ";
+ if (hasCaption) m_t << "{\\comment "; // to prevent caption to be shown
}
- m_lastIsPara=TRUE;
}
else // other format -> skip
{
@@ -1126,22 +1179,29 @@ void RTFDocVisitor::includePicturePreRTF(const QCString name, const bool isTypeR
void RTFDocVisitor::visitPost(DocImage *img)
{
DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocImage)}\n");
- includePicturePostRTF(img->type()==DocImage::Rtf, img->hasCaption());
+ includePicturePostRTF(img->type()==DocImage::Rtf, img->hasCaption(), img->isInlineImage());
}
-void RTFDocVisitor::includePicturePostRTF(const bool isTypeRTF, const bool hasCaption)
+void RTFDocVisitor::includePicturePostRTF(bool isTypeRTF, bool hasCaption, bool inlineImage)
{
if (isTypeRTF)
{
if (m_hide) return;
- if (hasCaption)
+ if (inlineImage)
{
- m_t << "}" <<endl;
- m_t << "\\par}" <<endl;
+ if (hasCaption) m_t << " }";
}
else
{
- m_t << "}" <<endl;
+ if (hasCaption)
+ {
+ m_t << "}" <<endl;
+ m_t << "\\par}" <<endl;
+ }
+ else
+ {
+ m_t << "}" <<endl;
+ }
}
}
else
@@ -1757,7 +1817,7 @@ void RTFDocVisitor::writeDotFile(DocDotFile *df)
{
writeDotFile(df->file(), df->hasCaption());
}
-void RTFDocVisitor::writeDotFile(const QCString &filename, const bool hasCaption)
+void RTFDocVisitor::writeDotFile(const QCString &filename, bool hasCaption)
{
QCString baseName=filename;
int i;
@@ -1775,7 +1835,7 @@ void RTFDocVisitor::writeMscFile(DocMscFile *df)
{
writeMscFile(df->file(), df->hasCaption());
}
-void RTFDocVisitor::writeMscFile(const QCString &fileName, const bool hasCaption)
+void RTFDocVisitor::writeMscFile(const QCString &fileName, bool hasCaption)
{
QCString baseName=fileName;
int i;
@@ -1801,7 +1861,7 @@ void RTFDocVisitor::writeDiaFile(DocDiaFile *df)
includePicturePreRTF(baseName + ".png", true, df->hasCaption());
}
-void RTFDocVisitor::writePlantUMLFile(const QCString &fileName, const bool hasCaption)
+void RTFDocVisitor::writePlantUMLFile(const QCString &fileName, bool hasCaption)
{
QCString baseName=fileName;
int i;
diff --git a/src/rtfdocvisitor.h b/src/rtfdocvisitor.h
index 1e927e7..b7cc3ea 100644
--- a/src/rtfdocvisitor.h
+++ b/src/rtfdocvisitor.h
@@ -40,6 +40,7 @@ class RTFDocVisitor : public DocVisitor
void visit(DocLinkedWord *);
void visit(DocWhiteSpace *);
void visit(DocSymbol *);
+ void visit(DocEmoji *);
void visit(DocURL *);
void visit(DocLineBreak *);
void visit(DocHorRuler *);
@@ -152,14 +153,14 @@ class RTFDocVisitor : public DocVisitor
void pushEnabled();
void popEnabled();
- void includePicturePreRTF(const QCString name, const bool isTypeRTF, const bool hasCaption);
- void includePicturePostRTF(const bool isTypeRTF, const bool hasCaption);
- void writeDotFile(const QCString &fileName, const bool hasCaption);
+ void includePicturePreRTF(const QCString name, bool isTypeRTF, bool hasCaption, bool inlineImage = FALSE);
+ void includePicturePostRTF(bool isTypeRTF, bool hasCaption, bool inlineImage = FALSE);
+ void writeDotFile(const QCString &fileName, bool hasCaption);
void writeDotFile(DocDotFile *);
- void writeMscFile(const QCString &fileName, const bool hasCaption);
+ void writeMscFile(const QCString &fileName, bool hasCaption);
void writeMscFile(DocMscFile *);
void writeDiaFile(DocDiaFile *);
- void writePlantUMLFile(const QCString &fileName, const bool hasCaption);
+ void writePlantUMLFile(const QCString &fileName, bool hasCaption);
//--------------------------------------
// state variables
diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp
index b4a9e65..34af705 100644
--- a/src/rtfgen.cpp
+++ b/src/rtfgen.cpp
@@ -2180,11 +2180,12 @@ void RTFGenerator::newParagraph()
m_omitParagraph = FALSE;
}
-void RTFGenerator::startParagraph(const char *)
+void RTFGenerator::startParagraph(const char *txt)
{
DBG_RTF(t << "{\\comment startParagraph}" << endl)
newParagraph();
t << "{" << endl;
+ if (QCString(txt) == "reference") t << "\\ql" << endl;
}
void RTFGenerator::endParagraph()
diff --git a/src/scanner.l b/src/scanner.l
index 4846132..7559e0b 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -31,7 +31,7 @@
#include <qstack.h>
#include <qregexp.h>
#include <qfile.h>
-
+
#include "scanner.h"
#include "entry.h"
#include "message.h"
@@ -126,8 +126,11 @@ static bool insidePHP = FALSE; //!< processing PHP code?
static bool insideObjC = FALSE; //!< processing Objective C code?
static bool insideCli = FALSE; //!< processing C++/CLI code?
static bool insideJS = FALSE; //!< processing JavaScript code?
+static bool insideSlice = FALSE; //!< processing Slice code?
static bool insideCpp = TRUE; //!< processing C/C++ code
+static bool sliceOpt = FALSE;
+
static bool insideCppQuote = FALSE;
static bool insideProtocolList = FALSE;
@@ -219,6 +222,7 @@ static void initParser()
insideFormula = FALSE;
insideCode=FALSE;
insideCli=Config_getBool(CPP_CLI_SUPPORT);
+ sliceOpt=Config_getBool(OPTIMIZE_OUTPUT_SLICE);
previous = 0;
firstTypedefEntry = 0;
tempEntry = 0;
@@ -376,15 +380,16 @@ static bool nameIsOperator(QCString &name)
static void setContext()
{
QCString fileName = yyFileName;
- language = getLanguageFromFileName(fileName);
- insideIDL = language==SrcLangExt_IDL;
- insideJava = language==SrcLangExt_Java;
- insideCS = language==SrcLangExt_CSharp;
- insideD = language==SrcLangExt_D;
- insidePHP = language==SrcLangExt_PHP;
- insideObjC = language==SrcLangExt_ObjC;
- insideJS = language==SrcLangExt_JS;
- insideCpp = language==SrcLangExt_Cpp;
+ language = getLanguageFromFileName(fileName);
+ insideIDL = language==SrcLangExt_IDL;
+ insideJava = language==SrcLangExt_Java;
+ insideCS = language==SrcLangExt_CSharp;
+ insideD = language==SrcLangExt_D;
+ insidePHP = language==SrcLangExt_PHP;
+ insideObjC = language==SrcLangExt_ObjC;
+ insideJS = language==SrcLangExt_JS;
+ insideSlice = language==SrcLangExt_Slice;
+ insideCpp = language==SrcLangExt_Cpp;
if ( insidePHP )
{
useOverrideCommands = TRUE;
@@ -597,15 +602,11 @@ static int yyread(char *buf,int max_size)
/* start command character */
CMD ("\\"|"@")
-SECTIONCMD {CMD}("image"|"author"|"internal"|"version"|"date"|"deprecated"|"param"|"exception"|"return"[s]?|"retval"|"bug"|"warning"|"par"|"sa"|"see"|"pre"|"post"|"invariant"|"note"|"remark"[s]?|"todo"|"test"|"xrefitem"|"ingroup"|"callgraph"|"callergraph"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"manonly"|"{"|"verbatim"|"dotfile"|"dot"|"defgroup"|"addtogroup"|"weakgroup"|"class"|"namespace"|"union"|"struct"|"fn"|"var"|"details"|"typedef"|"def"|"overload")|("<"{PRE}">")
BN [ \t\n\r]
BL [ \t\r]*"\n"
B [ \t]
-BS ^(({B}*"//")?)(({B}*"*"+)?){B}*
ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
-SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
SCOPENAME "$"?(({ID}?{BN}*"::"{BN}*)*)(((~|!){BN}*)?{ID})
-PHPSCOPENAME ({ID}"\\")+{ID}
TSCOPE {ID}("<"[a-z_A-Z0-9 \t\*\&,:]*">")?
CSSCOPENAME (({ID}?{BN}*"."{BN}*)*)((~{BN}*)?{ID})
PRE [pP][rR][eE]
@@ -763,6 +764,14 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
%x IDLProp
%x IDLPropName
+ /** Slice states */
+
+%x SliceMetadata
+%x SliceSequence
+%x SliceSequenceName
+%x SliceDictionary
+%x SliceDictionaryName
+
/** Prototype scanner states */
%x Prototype
@@ -1220,6 +1229,38 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
unput('{');
BEGIN( Function );
}
+<FindMembers>{B}*"sequence"{BN}*"<"{BN}* {
+ if (insideSlice)
+ {
+ lineCount();
+ current->bodyLine = yyLineNr;
+ current->fileName = yyFileName ;
+ current->startLine = yyLineNr ;
+ current->startColumn = yyColNr;
+ current->args.resize(0);
+ current->section = Entry::TYPEDEF_SEC ;
+ isTypedef = TRUE;
+ BEGIN( SliceSequence );
+ }
+ else
+ REJECT;
+ }
+<FindMembers>{B}*"dictionary"{BN}*"<"{BN}* {
+ if (insideSlice)
+ {
+ lineCount();
+ current->bodyLine = yyLineNr;
+ current->fileName = yyFileName ;
+ current->startLine = yyLineNr ;
+ current->startColumn = yyColNr;
+ current->args.resize(0);
+ current->section = Entry::TYPEDEF_SEC ;
+ isTypedef = TRUE;
+ BEGIN( SliceDictionary );
+ }
+ else
+ REJECT;
+ }
<FindMembers>{BN}{1,80} {
lineCount();
}
@@ -1392,6 +1433,9 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
<FindMembers>{B}*"explicit"{BN}+ { current->spec|=Entry::Explicit;
lineCount();
}
+<FindMembers>{B}*"local"{BN}+ { current->spec|=Entry::Local;
+ lineCount();
+ }
<FindMembers>{B}*"@required"{BN}+ { // Objective C 2.0 protocol required section
current->spec=(current->spec & ~Entry::Optional) | Entry::Required;
lineCount();
@@ -1426,7 +1470,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
}
<FindMembers>{B}*"module"{BN}+ {
lineCount();
- if (insideIDL)
+ if (insideIDL || insideSlice)
{
isTypedef=FALSE;
current->section = Entry::NAMESPACE_SEC;
@@ -1529,15 +1573,15 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
current->name = QCString(yytext).stripWhiteSpace();
}
}
-<FindMembers>{BN}*((("disp")?"interface")|"valuetype"){BN}+ { // M$/Corba/UNO IDL/Java interface
+<FindMembers>{BN}*((("disp")?"interface")|"valuetype"){BN}+ { // M$/Corba/UNO IDL/Java/Slice interface
lineCount();
- if (insideIDL || insideJava || insideCS || insideD || insidePHP)
+ if (insideIDL || insideJava || insideCS || insideD || insidePHP || insideSlice)
{
isTypedef=FALSE;
current->section = Entry::CLASS_SEC;
- current->spec = Entry::Interface |
- // preserve UNO IDL [optional] or published
- (current->spec & (Entry::Optional|Entry::Published));
+ current->spec = Entry::Interface |
+ // preserve UNO IDL [optional], published, Slice local
+ (current->spec & (Entry::Optional|Entry::Published|Entry::Local));
addType( current ) ;
current->type += " interface" ;
current->fileName = yyFileName;
@@ -1601,11 +1645,13 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
current->bodyLine = yyLineNr;
BEGIN( CompoundName );
}
-<FindMembers>{B}*"exception"{BN}+ { // Corba IDL exception
+<FindMembers>{B}*"exception"{BN}+ { // Corba IDL/Slice exception
isTypedef=FALSE;
current->section = Entry::CLASS_SEC;
+ // preserve UNO IDL, Slice local
current->spec = Entry::Exception |
- (current->spec & Entry::Published); // preserve UNO IDL
+ (current->spec & Entry::Published) |
+ (current->spec & Entry::Local);
addType( current ) ;
current->type += " exception" ;
current->fileName = yyFileName;
@@ -1624,6 +1670,16 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
bool isVolatile=decl.find("volatile")!=-1;
current->section = Entry::CLASS_SEC;
addType( current ) ;
+ uint64 spec = current->spec;
+ if (insidePHP && current->spec&Entry::Abstract)
+ {
+ // convert Abstract to AbstractClass
+ current->spec=(current->spec&~Entry::Abstract)|Entry::AbstractClass;
+ }
+ if (insideSlice && spec&Entry::Local)
+ {
+ current->spec|=Entry::Local;
+ }
if (isConst)
{
current->type += " const";
@@ -1644,11 +1700,6 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
}
lineCount() ;
if (yytext[yyleng-1]=='{') unput('{');
- if (insidePHP && current->spec&Entry::Abstract)
- {
- // convert Abstract to AbstractClass
- current->spec=(current->spec&~Entry::Abstract)|Entry::AbstractClass;
- }
BEGIN( CompoundName ) ;
}
<FindMembers>{B}*"value class{" | // C++/CLI extension
@@ -1724,10 +1775,13 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
isTypedef=decl.find("typedef")!=-1;
bool isConst=decl.find("const")!=-1;
bool isVolatile=decl.find("volatile")!=-1;
+ uint64 spec = current->spec;
current->section = Entry::CLASS_SEC ;
+ // preserve UNO IDL & Inline attributes, Slice local
current->spec = Entry::Struct |
(current->spec & Entry::Published) |
- (current->spec & Entry::Inline); // preserve UNO IDL & Inline attributes
+ (current->spec & Entry::Inline) |
+ (current->spec & Entry::Local);
// bug 582676: can be a struct nested in an interface so keep insideObjC state
//current->objc = insideObjC = FALSE;
addType( current ) ;
@@ -3079,6 +3133,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
*pCopyQuotedGString+=*yytext;
BEGIN( lastStringContext );
}
+<CopyGString,CopyPHPGString>"<?php" { // we had an odd number of quotes.
+ *pCopyQuotedGString += yytext;
+ BEGIN( lastStringContext );
+ }
<CopyGString,CopyPHPGString>"/*"|"*/"|"//" {
*pCopyQuotedGString+=yytext;
}
@@ -3448,7 +3506,14 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
}
<FindMembers>"[" {
- if (!insideCS &&
+ if (insideSlice)
+ {
+ squareCount=1;
+ lastSquareContext = YY_START;
+ current->metaData += "[";
+ BEGIN( SliceMetadata );
+ }
+ else if (!insideCS &&
(current->name.isEmpty() ||
current->name=="typedef"
)
@@ -3488,6 +3553,26 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
BEGIN( Array ) ;
}
}
+<SliceMetadata>"[" { // Global metadata.
+ squareCount++;
+ current->metaData += "[";
+ }
+<SliceMetadata>{BN}* {
+ lineCount();
+ }
+<SliceMetadata>\"[^\"]*\" {
+ current->metaData += yytext;
+ }
+<SliceMetadata>"," {
+ current->metaData += yytext;
+ }
+<SliceMetadata>"]" {
+ current->metaData += yytext;
+ if (--squareCount<=0)
+ {
+ BEGIN (lastSquareContext);
+ }
+ }
<IDLAttribute>"]" {
// end of IDL function attribute
if (--squareCount<=0)
@@ -3840,6 +3925,28 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
else
{
current->endBodyLine = yyLineNr;
+ if (current->section == Entry::NAMESPACE_SEC && current->type == "namespace")
+ {
+ int split_point;
+ while ((split_point = current->name.find("::")) != -1)
+ {
+ Entry *new_current = new Entry(*current);
+ current->program = "";
+ new_current->doc = "";
+ new_current->docLine = 0;
+ new_current->docFile = "";
+ new_current->brief = "";
+ new_current->briefLine = 0;
+ new_current->briefFile = "";
+ new_current->name = current->name.mid(split_point + 2);
+ current->name = current->name.left(split_point);
+ if (!current_root->name.isEmpty()) current->name.prepend(current_root->name+"::");
+
+ current_root->addSubEntry(current);
+ current_root = current;
+ current = new_current;
+ }
+ }
QCString &cn = current->name;
QCString rn = current_root->name.copy();
//printf("cn=`%s' rn=`%s' isTypedef=%d\n",cn.data(),rn.data(),isTypedef);
@@ -3877,7 +3984,8 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
current = new Entry(*current);
if (current->section==Entry::NAMESPACE_SEC ||
(current->spec==Entry::Interface) ||
- insideJava || insidePHP || insideCS || insideD || insideJS
+ insideJava || insidePHP || insideCS || insideD || insideJS ||
+ insideSlice
)
{ // namespaces and interfaces and java classes ends with a closing bracket without semicolon
current->reset();
@@ -5349,7 +5457,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
}
BEGIN( FindMembers ) ;
}
-<CompoundName>{SCOPENAME}{BN}*/"<" {
+<CompoundName>{SCOPENAME}/{BN}*"<" {
sharpCount = 0;
current->name = yytext ;
if (current->spec & Entry::Protocol)
@@ -5587,7 +5695,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
roundCount=0;
BEGIN(SkipUnionSwitch);
}
- else if ((insideJava || insidePHP || insideJS) && (qstrcmp(yytext,"implements")==0 || qstrcmp(yytext,"extends")==0))
+ else if ((insideJava || insidePHP || insideJS || insideSlice) && (qstrcmp(yytext,"implements")==0 || qstrcmp(yytext,"extends")==0))
{
current->type.resize(0);
baseProt=Public;
@@ -6014,7 +6122,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
}
if ((current->spec & (Entry::Interface|Entry::Struct)) ||
insideJava || insidePHP || insideCS ||
- insideD || insideObjC || insideIDL)
+ insideD || insideObjC || insideIDL || insideSlice)
{
baseProt=Public;
}
@@ -6304,8 +6412,67 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
<CSString>\n { lineCount(); }
<CSString>"." {}
+ /* ---- Slice-specific rules ------ */
+<SliceSequence>{SCOPENAME} {
+ if (current->spec&Entry::Local)
+ {
+ current->type = "local ";
+ }
+ current->type += "sequence<";
+ current->type += yytext;
+ current->type += ">";
+ }
+<SliceSequence>{BN}*">"{BN}* {
+ lineCount();
+ BEGIN(SliceSequenceName);
+ }
+
+<SliceSequenceName>{ID}{BN}* {
+ lineCount();
+ current->name = yytext ;
+ current->name = current->name.stripWhiteSpace();
+ }
+
+<SliceSequenceName>";" {
+ current->section = Entry::VARIABLE_SEC;
+ current_root->addSubEntry(current);
+ current = new Entry;
+ initEntry();
+ BEGIN(FindMembers);
+ }
+
+<SliceDictionary>{SCOPENAME}{BN}*","{BN}*{SCOPENAME} {
+ lineCount();
+ if (current->spec&Entry::Local)
+ {
+ current->type = "local ";
+ }
+ current->type += "dictionary<";
+ current->type += yytext;
+ current->type += ">";
+ current->type = current->type.simplifyWhiteSpace();
+ }
+
+<SliceDictionary>{BN}*">"{BN}* {
+ lineCount();
+ BEGIN(SliceDictionaryName);
+ }
+
+<SliceDictionaryName>{ID}{BN}* {
+ lineCount();
+ current->name = yytext ;
+ current->name = current->name.stripWhiteSpace();
+ }
+
+<SliceDictionaryName>";" {
+ current->section = Entry::VARIABLE_SEC;
+ current_root->addSubEntry(current);
+ current = new Entry;
+ initEntry();
+ BEGIN(FindMembers);
+ }
/**********************************************************************************/
/******************** Documentation block related rules ***************************/
@@ -6901,7 +7068,7 @@ static void parseCompounds(Entry *rt)
// set default protection based on the compound type
if( ce->section==Entry::CLASS_SEC ) // class
{
- if (insidePHP || insideD || insideJS || insideIDL)
+ if (insidePHP || insideD || insideJS || insideIDL || insideSlice)
{
current->protection = protection = Public ;
}
diff --git a/src/searchindex.cpp b/src/searchindex.cpp
index 6276eae..5859d67 100644
--- a/src/searchindex.cpp
+++ b/src/searchindex.cpp
@@ -620,6 +620,14 @@ static void addMemberToSearchIndex(MemberDef *md)
{
g_searchIndexInfo[SEARCH_INDEX_VARIABLES].symbolList.append(letter,md);
}
+ else if (md->isSequence())
+ {
+ g_searchIndexInfo[SEARCH_INDEX_SEQUENCES].symbolList.append(letter,md);
+ }
+ else if (md->isDictionary())
+ {
+ g_searchIndexInfo[SEARCH_INDEX_DICTIONARIES].symbolList.append(letter,md);
+ }
else if (md->isTypedef())
{
g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].symbolList.append(letter,md);
@@ -667,6 +675,14 @@ static void addMemberToSearchIndex(MemberDef *md)
{
g_searchIndexInfo[SEARCH_INDEX_VARIABLES].symbolList.append(letter,md);
}
+ else if (md->isSequence())
+ {
+ g_searchIndexInfo[SEARCH_INDEX_SEQUENCES].symbolList.append(letter,md);
+ }
+ else if (md->isDictionary())
+ {
+ g_searchIndexInfo[SEARCH_INDEX_DICTIONARIES].symbolList.append(letter,md);
+ }
else if (md->isTypedef())
{
g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].symbolList.append(letter,md);
@@ -717,39 +733,54 @@ static QCString searchId(const QCString &s)
void createJavascriptSearchIndex()
{
+ bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
+
// set index names
- g_searchIndexInfo[SEARCH_INDEX_ALL].name = "all";
- g_searchIndexInfo[SEARCH_INDEX_CLASSES].name = "classes";
- g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].name = "namespaces";
- g_searchIndexInfo[SEARCH_INDEX_FILES].name = "files";
- g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].name = "functions";
- g_searchIndexInfo[SEARCH_INDEX_VARIABLES].name = "variables";
- g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].name = "typedefs";
- g_searchIndexInfo[SEARCH_INDEX_ENUMS].name = "enums";
- g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].name = "enumvalues";
- g_searchIndexInfo[SEARCH_INDEX_PROPERTIES].name = "properties";
- g_searchIndexInfo[SEARCH_INDEX_EVENTS].name = "events";
- g_searchIndexInfo[SEARCH_INDEX_RELATED].name = "related";
- g_searchIndexInfo[SEARCH_INDEX_DEFINES].name = "defines";
- g_searchIndexInfo[SEARCH_INDEX_GROUPS].name = "groups";
- g_searchIndexInfo[SEARCH_INDEX_PAGES].name = "pages";
+ g_searchIndexInfo[SEARCH_INDEX_ALL].name = "all";
+ g_searchIndexInfo[SEARCH_INDEX_CLASSES].name = "classes";
+ g_searchIndexInfo[SEARCH_INDEX_INTERFACES].name = "interfaces";
+ g_searchIndexInfo[SEARCH_INDEX_STRUCTS].name = "structs";
+ g_searchIndexInfo[SEARCH_INDEX_EXCEPTIONS].name = "exceptions";
+ g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].name = "namespaces";
+ g_searchIndexInfo[SEARCH_INDEX_FILES].name = "files";
+ g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].name = "functions";
+ g_searchIndexInfo[SEARCH_INDEX_VARIABLES].name = "variables";
+ g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].name = "typedefs";
+ g_searchIndexInfo[SEARCH_INDEX_SEQUENCES].name = "sequences";
+ g_searchIndexInfo[SEARCH_INDEX_DICTIONARIES].name = "dictionaries";
+ g_searchIndexInfo[SEARCH_INDEX_ENUMS].name = "enums";
+ g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].name = "enumvalues";
+ g_searchIndexInfo[SEARCH_INDEX_PROPERTIES].name = "properties";
+ g_searchIndexInfo[SEARCH_INDEX_EVENTS].name = "events";
+ g_searchIndexInfo[SEARCH_INDEX_RELATED].name = "related";
+ g_searchIndexInfo[SEARCH_INDEX_DEFINES].name = "defines";
+ g_searchIndexInfo[SEARCH_INDEX_GROUPS].name = "groups";
+ g_searchIndexInfo[SEARCH_INDEX_PAGES].name = "pages";
// set index texts
- g_searchIndexInfo[SEARCH_INDEX_ALL].text = theTranslator->trAll();
- g_searchIndexInfo[SEARCH_INDEX_CLASSES].text = theTranslator->trClasses();
- g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].text = theTranslator->trNamespace(TRUE,FALSE);
- g_searchIndexInfo[SEARCH_INDEX_FILES].text = theTranslator->trFile(TRUE,FALSE);
- g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].text = theTranslator->trFunctions();
- g_searchIndexInfo[SEARCH_INDEX_VARIABLES].text = theTranslator->trVariables();
- g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].text = theTranslator->trTypedefs();
- g_searchIndexInfo[SEARCH_INDEX_ENUMS].text = theTranslator->trEnumerations();
- g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].text = theTranslator->trEnumerationValues();
- g_searchIndexInfo[SEARCH_INDEX_PROPERTIES].text = theTranslator->trProperties();
- g_searchIndexInfo[SEARCH_INDEX_EVENTS].text = theTranslator->trEvents();
- g_searchIndexInfo[SEARCH_INDEX_RELATED].text = theTranslator->trFriends();
- g_searchIndexInfo[SEARCH_INDEX_DEFINES].text = theTranslator->trDefines();
- g_searchIndexInfo[SEARCH_INDEX_GROUPS].text = theTranslator->trGroup(TRUE,FALSE);
- g_searchIndexInfo[SEARCH_INDEX_PAGES].text = theTranslator->trPage(TRUE,FALSE);
+ g_searchIndexInfo[SEARCH_INDEX_ALL].text = theTranslator->trAll();
+ g_searchIndexInfo[SEARCH_INDEX_CLASSES].text = theTranslator->trClasses();
+ g_searchIndexInfo[SEARCH_INDEX_INTERFACES].text = theTranslator->trSliceInterfaces();
+ g_searchIndexInfo[SEARCH_INDEX_STRUCTS].text = theTranslator->trStructs();
+ g_searchIndexInfo[SEARCH_INDEX_EXCEPTIONS].text = theTranslator->trExceptions();
+ g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].text = sliceOpt ? theTranslator->trModules() :
+ theTranslator->trNamespace(TRUE,FALSE);
+ g_searchIndexInfo[SEARCH_INDEX_FILES].text = theTranslator->trFile(TRUE,FALSE);
+ g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].text = sliceOpt ? theTranslator->trOperations() :
+ theTranslator->trFunctions();
+ g_searchIndexInfo[SEARCH_INDEX_VARIABLES].text = sliceOpt ? theTranslator->trConstants() :
+ theTranslator->trVariables();
+ g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].text = theTranslator->trTypedefs();
+ g_searchIndexInfo[SEARCH_INDEX_SEQUENCES].text = theTranslator->trSequences();
+ g_searchIndexInfo[SEARCH_INDEX_DICTIONARIES].text = theTranslator->trDictionaries();
+ g_searchIndexInfo[SEARCH_INDEX_ENUMS].text = theTranslator->trEnumerations();
+ g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].text = theTranslator->trEnumerationValues();
+ g_searchIndexInfo[SEARCH_INDEX_PROPERTIES].text = theTranslator->trProperties();
+ g_searchIndexInfo[SEARCH_INDEX_EVENTS].text = theTranslator->trEvents();
+ g_searchIndexInfo[SEARCH_INDEX_RELATED].text = theTranslator->trFriends();
+ g_searchIndexInfo[SEARCH_INDEX_DEFINES].text = theTranslator->trDefines();
+ g_searchIndexInfo[SEARCH_INDEX_GROUPS].text = theTranslator->trGroup(TRUE,FALSE);
+ g_searchIndexInfo[SEARCH_INDEX_PAGES].text = theTranslator->trPage(TRUE,FALSE);
// add symbols to letter -> symbol list map
@@ -762,7 +793,29 @@ void createJavascriptSearchIndex()
if (cd->isLinkable() && isId(letter))
{
g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,cd);
- g_searchIndexInfo[SEARCH_INDEX_CLASSES].symbolList.append(letter,cd);
+ if (sliceOpt)
+ {
+ if (cd->compoundType()==ClassDef::Interface)
+ {
+ g_searchIndexInfo[SEARCH_INDEX_INTERFACES].symbolList.append(letter,cd);
+ }
+ else if (cd->compoundType()==ClassDef::Struct)
+ {
+ g_searchIndexInfo[SEARCH_INDEX_STRUCTS].symbolList.append(letter,cd);
+ }
+ else if (cd->compoundType()==ClassDef::Exception)
+ {
+ g_searchIndexInfo[SEARCH_INDEX_EXCEPTIONS].symbolList.append(letter,cd);
+ }
+ else // cd->compoundType()==ClassDef::Class
+ {
+ g_searchIndexInfo[SEARCH_INDEX_CLASSES].symbolList.append(letter,cd);
+ }
+ }
+ else // non slice optimisation: group all types under classes
+ {
+ g_searchIndexInfo[SEARCH_INDEX_CLASSES].symbolList.append(letter,cd);
+ }
}
}
@@ -927,7 +980,7 @@ void writeJavascriptSearchIndex()
FTextStream t(&outFile);
t << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\""
- " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl;
+ " \"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl;
t << "<html><head><title></title>" << endl;
t << "<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>" << endl;
t << "<meta name=\"generator\" content=\"Doxygen " << versionString << "\"/>" << endl;
@@ -1231,7 +1284,7 @@ void writeJavascriptSearchIndex()
{
FTextStream t(&f);
t << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" "
- "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl;
+ "\"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl;
t << "<html><head><title></title>" << endl;
t << "<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>" << endl;
t << "<link rel=\"stylesheet\" type=\"text/css\" href=\"search.css\"/>" << endl;
diff --git a/src/searchindex.h b/src/searchindex.h
index e491f47..0345b41 100644
--- a/src/searchindex.h
+++ b/src/searchindex.h
@@ -112,22 +112,27 @@ class SearchIndexExternal : public SearchIndexIntf
//------- client side search index ----------------------
-#define SEARCH_INDEX_ALL 0
-#define SEARCH_INDEX_CLASSES 1
-#define SEARCH_INDEX_NAMESPACES 2
-#define SEARCH_INDEX_FILES 3
-#define SEARCH_INDEX_FUNCTIONS 4
-#define SEARCH_INDEX_VARIABLES 5
-#define SEARCH_INDEX_TYPEDEFS 6
-#define SEARCH_INDEX_ENUMS 7
-#define SEARCH_INDEX_ENUMVALUES 8
-#define SEARCH_INDEX_PROPERTIES 9
-#define SEARCH_INDEX_EVENTS 10
-#define SEARCH_INDEX_RELATED 11
-#define SEARCH_INDEX_DEFINES 12
-#define SEARCH_INDEX_GROUPS 13
-#define SEARCH_INDEX_PAGES 14
-#define NUM_SEARCH_INDICES 15
+#define SEARCH_INDEX_ALL 0
+#define SEARCH_INDEX_CLASSES 1
+#define SEARCH_INDEX_INTERFACES 2
+#define SEARCH_INDEX_STRUCTS 3
+#define SEARCH_INDEX_EXCEPTIONS 4
+#define SEARCH_INDEX_NAMESPACES 5
+#define SEARCH_INDEX_FILES 6
+#define SEARCH_INDEX_FUNCTIONS 7
+#define SEARCH_INDEX_VARIABLES 8
+#define SEARCH_INDEX_TYPEDEFS 9
+#define SEARCH_INDEX_SEQUENCES 10
+#define SEARCH_INDEX_DICTIONARIES 11
+#define SEARCH_INDEX_ENUMS 12
+#define SEARCH_INDEX_ENUMVALUES 13
+#define SEARCH_INDEX_PROPERTIES 14
+#define SEARCH_INDEX_EVENTS 15
+#define SEARCH_INDEX_RELATED 16
+#define SEARCH_INDEX_DEFINES 17
+#define SEARCH_INDEX_GROUPS 18
+#define SEARCH_INDEX_PAGES 19
+#define NUM_SEARCH_INDICES 20
class SearchDefinitionList : public QList<Definition>
{
diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp
index 6cd9581..a7b8dbb 100644
--- a/src/sqlite3gen.cpp
+++ b/src/sqlite3gen.cpp
@@ -23,11 +23,15 @@
#include "qtbc.h"
#include "sqlite3gen.h"
#include "doxygen.h"
+#include "xmlgen.h"
+#include "xmldocvisitor.h"
#include "config.h"
#include "util.h"
+#include "outputlist.h"
#include "docparser.h"
#include "language.h"
+#include "version.h"
#include "dot.h"
#include "arguments.h"
#include "classlist.h"
@@ -35,65 +39,129 @@
#include "namespacedef.h"
#include "filename.h"
#include "groupdef.h"
+#include "membername.h"
+#include "memberdef.h"
#include "pagedef.h"
#include "dirdef.h"
+#include "section.h"
+#include <sys/stat.h>
#include <qdir.h>
#include <string.h>
#include <sqlite3.h>
-//#define DBG_CTX(x) printf x
-#define DBG_CTX(x) do { } while(0)
+// enable to show general debug messages
+// #define SQLITE3_DEBUG
-const char * schema_queries[][2] = {
+// enable to print all executed SQL statements.
+// I recommend using the smallest possible input list.
+// #define SQLITE3_DEBUG_SQL
+
+# ifdef SQLITE3_DEBUG
+# define DBG_CTX(x) printf x
+# else // SQLITE3_DEBUG
+# define DBG_CTX(x) do { } while(0)
+# endif
+
+# ifdef SQLITE3_DEBUG_SQL
+// used by sqlite3_trace in generateSqlite3()
+static void sqlLog(void *dbName, const char *sql){
+ msg("SQL: '%s'\n", sql);
+}
+# endif
+
+const char * table_schema[][2] = {
+ /* TABLES */
+ { "meta",
+ "CREATE TABLE IF NOT EXISTS meta (\n"
+ "\t-- Information about this db and how it was generated.\n"
+ "\t-- Doxygen info\n"
+ "\tdoxygen_version TEXT PRIMARY KEY NOT NULL,\n"
+ /*
+ Doxygen's version is likely to rollover much faster than the schema, and
+ at least until it becomes a core output format, we might want to make
+ fairly large schema changes even on minor iterations for Doxygen itself.
+ If these tools just track a predefined semver schema version that can
+ iterate independently, it *might* not be as hard to keep them in sync?
+ */
+ "\tschema_version TEXT NOT NULL, -- Schema-specific semver\n"
+ "\t-- run info\n"
+ "\tgenerated_at TEXT NOT NULL,\n"
+ "\tgenerated_on TEXT NOT NULL,\n"
+ "\t-- project info\n"
+ "\tproject_name TEXT NOT NULL,\n"
+ "\tproject_number TEXT,\n"
+ "\tproject_brief TEXT\n"
+ ");"
+ },
{ "includes",
"CREATE TABLE IF NOT EXISTS includes (\n"
"\t-- #include relations.\n"
"\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
"\tlocal INTEGER NOT NULL,\n"
- "\tid_src INTEGER NOT NULL, -- File id of the includer.\n"
- "\tid_dst INTEGER NOT NULL -- File id of the includee.\n"
- ");\n"
- "CREATE UNIQUE INDEX idx_includes ON includes\n"
- "\t(local, id_src, id_dst);"
+ "\tsrc_id INTEGER NOT NULL REFERENCES path, -- File id of the includer.\n"
+ "\tdst_id INTEGER NOT NULL REFERENCES path, -- File id of the includee.\n"
+ /*
+ In theory we could include name here to be informationally equivalent
+ with the XML, but I don't see an obvious use for it.
+ */
+ "\tUNIQUE(local, src_id, dst_id) ON CONFLICT IGNORE\n"
+ ");"
},
- { "innerclass",
- "CREATE TABLE IF NOT EXISTS innerclass (\n"
+ { "contains",
+ "CREATE TABLE IF NOT EXISTS contains (\n"
+ "\t-- inner/outer relations (file, namespace, dir, class, group, page)\n"
"\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
- "\trefid INTEGER NOT NULL,\n"
- "\tprot INTEGER NOT NULL,\n"
- "\tname TEXT NOT NULL\n"
- ");"
+ "\tinner_rowid INTEGER NOT NULL REFERENCES compounddef,\n"
+ "\touter_rowid INTEGER NOT NULL REFERENCES compounddef\n"
+ ");"
},
- { "files",
- "CREATE TABLE IF NOT EXISTS files (\n"
- "\t-- Names of source files and includes.\n"
- "\tname TEXT PRIMARY KEY NOT NULL\n"
- ");"
+ /* TODO: Path can also share rowids with refid/compounddef/def. (It could
+ * even collapse into that table...)
+ *
+ * I took a first swing at this by changing insertPath() to:
+ * - accept a FileDef
+ * - make its own call to insertRefid
+ * - return a refid struct.
+ *
+ * I rolled this back when I had trouble getting a FileDef for all types
+ * (PageDef in particular).
+ *
+ * Note: all colums referencing path would need an update.
+ */
+ { "path",
+ "CREATE TABLE IF NOT EXISTS path (\n"
+ "\t-- Paths of source files and includes.\n"
+ "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
+ "\ttype INTEGER NOT NULL, -- 1:file 2:dir\n"
+ "\tlocal INTEGER NOT NULL,\n"
+ "\tfound INTEGER NOT NULL,\n"
+ "\tname TEXT NOT NULL\n"
+ ");"
},
- { "refids",
- "CREATE TABLE IF NOT EXISTS refids (\n"
- "\trefid TEXT PRIMARY KEY NOT NULL\n"
- ");"
+ { "refid",
+ "CREATE TABLE IF NOT EXISTS refid (\n"
+ "\t-- Distinct refid for all documented entities.\n"
+ "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
+ "\trefid TEXT NOT NULL UNIQUE\n"
+ ");"
},
{ "xrefs",
"CREATE TABLE IF NOT EXISTS xrefs (\n"
- "\t-- Cross reference relation.\n"
+ "\t-- Cross-reference relation\n"
+ "\t-- (combines xml <referencedby> and <references> nodes).\n"
"\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
- "\trefid_src INTEGER NOT NULL, -- referrer id.\n"
- "\trefid_dst INTEGER NOT NULL, -- referee id.\n"
- "\tid_file INTEGER NOT NULL, -- file where the reference is happening.\n"
- "\tline INTEGER NOT NULL, -- line where the reference is happening.\n"
- "\tcolumn INTEGER NOT NULL -- column where the reference is happening.\n"
- ");\n"
- "CREATE UNIQUE INDEX idx_xrefs ON xrefs\n"
- "\t(refid_src, refid_dst, id_file, line, column);"
+ "\tsrc_rowid INTEGER NOT NULL REFERENCES refid, -- referrer id.\n"
+ "\tdst_rowid INTEGER NOT NULL REFERENCES refid, -- referee id.\n"
+ "\tcontext TEXT NOT NULL, -- inline, argument, initializer\n"
+ "\t-- Just need to know they link; ignore duplicates.\n"
+ "\tUNIQUE(src_rowid, dst_rowid, context) ON CONFLICT IGNORE\n"
+ ");\n"
},
{ "memberdef",
"CREATE TABLE IF NOT EXISTS memberdef (\n"
"\t-- All processed identifiers.\n"
- "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
- "\trefid INTEGER NOT NULL, -- see the refids table\n"
+ "\trowid INTEGER PRIMARY KEY NOT NULL,\n"
"\tname TEXT NOT NULL,\n"
"\tdefinition TEXT,\n"
"\ttype TEXT,\n"
@@ -107,7 +175,7 @@ const char * schema_queries[][2] = {
"\tstatic INTEGER DEFAULT 0, -- 0:no 1:yes\n"
"\tconst INTEGER DEFAULT 0, -- 0:no 1:yes\n"
"\texplicit INTEGER DEFAULT 0, -- 0:no 1:yes\n"
- "\tinline INTEGER DEFAULT 0, -- 0:no 1:yes\n"
+ "\tinline INTEGER DEFAULT 0, -- 0:no 1:yes 2:both (set after encountering inline and not-inline)\n"
"\tfinal INTEGER DEFAULT 0, -- 0:no 1:yes\n"
"\tsealed INTEGER DEFAULT 0, -- 0:no 1:yes\n"
"\tnew INTEGER DEFAULT 0, -- 0:no 1:yes\n"
@@ -138,55 +206,71 @@ const char * schema_queries[][2] = {
"\taddable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
"\tremovable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
"\traisable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
- /// @todo make a `kind' table
- "\tkind INTEGER DEFAULT 0, -- 0:define 1:function 2:variable 3:typedef 4:enum 5:enumvalue 6:signal 7:slot 8:friend 9:DCOP 10:property 11:event\n"
+ "\tkind TEXT NOT NULL, -- 'macro definition' 'function' 'variable' 'typedef' 'enumeration' 'enumvalue' 'signal' 'slot' 'friend' 'dcop' 'property' 'event' 'interface' 'service'\n"
"\tbodystart INTEGER DEFAULT 0, -- starting line of definition\n"
"\tbodyend INTEGER DEFAULT 0, -- ending line of definition\n"
- "\tid_bodyfile INTEGER DEFAULT 0, -- file of definition\n"
- "\tid_file INTEGER NOT NULL, -- file where this identifier is located\n"
+ "\tbodyfile_id INTEGER REFERENCES path, -- file of definition\n"
+ "\tfile_id INTEGER NOT NULL REFERENCES path, -- file where this identifier is located\n"
"\tline INTEGER NOT NULL, -- line where this identifier is located\n"
"\tcolumn INTEGER NOT NULL, -- column where this identifier is located\n"
- /// @todo make a `detaileddescription' table
"\tdetaileddescription TEXT,\n"
"\tbriefdescription TEXT,\n"
- "\tinbodydescription TEXT\n"
- ");"
+ "\tinbodydescription TEXT,\n"
+ "\tFOREIGN KEY (rowid) REFERENCES refid (rowid)\n"
+ ");"
+ },
+ { "member",
+ "CREATE TABLE IF NOT EXISTS member (\n"
+ "\t-- Memberdef <-> containing compound relation.\n"
+ "\t-- Similar to XML listofallmembers.\n"
+ "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
+ "\tscope_rowid INTEGER NOT NULL REFERENCES compounddef,\n"
+ "\tmemberdef_rowid INTEGER NOT NULL REFERENCES memberdef,\n"
+ "\tprot INTEGER NOT NULL,\n"
+ "\tvirt INTEGER NOT NULL,\n"
+ "\tUNIQUE(scope_rowid, memberdef_rowid)\n"
+ ");"
+ },
+ { "reimplements",
+ "CREATE TABLE IF NOT EXISTS reimplements (\n"
+ "\t-- Inherited member reimplmentation relations.\n"
+ "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
+ "\tmemberdef_rowid INTEGER NOT NULL REFERENCES memberdef, -- reimplementing memberdef id.\n"
+ "\treimplemented_rowid INTEGER NOT NULL REFERENCES memberdef, -- reimplemented memberdef id.\n"
+ "\tUNIQUE(memberdef_rowid, reimplemented_rowid) ON CONFLICT IGNORE\n"
+ ");\n"
},
{ "compounddef",
"CREATE TABLE IF NOT EXISTS compounddef (\n"
- "\t-- class/struct definitions.\n"
- "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
- "\tname TEXT NOT NULL,\n"
- "\tkind TEXT NOT NULL,\n"
- "\trefid INTEGER NOT NULL,\n"
- "\tprot INTEGER NOT NULL,\n"
- "\tid_file INTEGER NOT NULL,\n"
- "\tline INTEGER NOT NULL,\n"
- "\tcolumn INTEGER NOT NULL\n"
- ");"
- },
- { "basecompoundref",
- "CREATE TABLE IF NOT EXISTS basecompoundref (\n"
- "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
- "\tbase TEXT NOT NULL,\n"
- "\tderived TEXT NOT NULL,\n"
- "\trefid INTEGER NOT NULL,\n"
- "\tprot INTEGER NOT NULL,\n"
- "\tvirt INTEGER NOT NULL\n"
- ");"
+ "\t-- Class/struct definitions.\n"
+ "\trowid INTEGER PRIMARY KEY NOT NULL,\n"
+ "\tname TEXT NOT NULL,\n"
+ "\ttitle TEXT,\n"
+ // probably won't be empty '' or unknown, but the source *could* return them...
+ "\tkind TEXT NOT NULL, -- 'category' 'class' 'constants' 'dir' 'enum' 'example' 'exception' 'file' 'group' 'interface' 'library' 'module' 'namespace' 'package' 'page' 'protocol' 'service' 'singleton' 'struct' 'type' 'union' 'unknown' ''\n"
+ "\tprot INTEGER,\n"
+ "\tfile_id INTEGER NOT NULL REFERENCES path,\n"
+ "\tline INTEGER NOT NULL,\n"
+ "\tcolumn INTEGER NOT NULL,\n"
+ "\theader_id INTEGER REFERENCES path,\n"
+ "\tdetaileddescription TEXT,\n"
+ "\tbriefdescription TEXT,\n"
+ "\tFOREIGN KEY (rowid) REFERENCES refid (rowid)\n"
+ ");"
},
- { "derivedcompoundref",
- "CREATE TABLE IF NOT EXISTS derivedcompoundref (\n"
- "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
- "\tbase TEXT NOT NULL,\n"
- "\tderived TEXT NOT NULL,\n"
- "\trefid INTEGER NOT NULL,\n"
- "\tprot INTEGER NOT NULL,\n"
- "\tvirt INTEGER NOT NULL\n"
- ");"
+ { "compoundref",
+ "CREATE TABLE IF NOT EXISTS compoundref (\n"
+ "\t-- Inheritance relation.\n"
+ "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
+ "\tbase_rowid INTEGER NOT NULL REFERENCES compounddef,\n"
+ "\tderived_rowid INTEGER NOT NULL REFERENCES compounddef,\n"
+ "\tprot INTEGER NOT NULL,\n"
+ "\tvirt INTEGER NOT NULL,\n"
+ "\tUNIQUE(base_rowid, derived_rowid)\n"
+ ");"
},
- { "params",
- "CREATE TABLE IF NOT EXISTS params (\n"
+ { "param",
+ "CREATE TABLE IF NOT EXISTS param (\n"
"\t-- All processed parameters.\n"
"\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
"\tattributes TEXT,\n"
@@ -196,24 +280,222 @@ const char * schema_queries[][2] = {
"\tarray TEXT,\n"
"\tdefval TEXT,\n"
"\tbriefdescription TEXT\n"
- ");"
- "CREATE UNIQUE INDEX idx_params ON params\n"
+ ");"
+ "CREATE UNIQUE INDEX idx_param ON param\n"
"\t(type, defname);"
},
- { "memberdef_params",
- "CREATE TABLE IF NOT EXISTS memberdef_params (\n"
+ { "memberdef_param",
+ "CREATE TABLE IF NOT EXISTS memberdef_param (\n"
"\t-- Junction table for memberdef parameters.\n"
"\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
- "\tid_memberdef INTEGER NOT NULL,\n"
- "\tid_param INTEGER NOT NULL\n"
- ");"
+ "\tmemberdef_id INTEGER NOT NULL REFERENCES memberdef,\n"
+ "\tparam_id INTEGER NOT NULL REFERENCES param\n"
+ ");"
},
- { "innernamespaces",
- "CREATE TABLE IF NOT EXISTS innernamespaces (\n"
- "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
- "\trefid INTEGER NOT NULL,\n"
- "\tname TEXT NOT NULL\n"
- ");"
+};
+ const char * view_schema[][2] = {
+ /* VIEWS *
+ We'll set these up AFTER we build the database, so that they can be indexed,
+ but so we don't have to pay a performance penalty for inserts as we build.
+ */
+ {
+ /*
+ Makes all reference/relation tables easier to use. For example:
+ 1. query xrefs and join this view on either xrefs.dst_rowid=def.rowid or
+ xrefs.src_rowid=def.rowid
+ 2. get everything you need to output a list of references to/from an entity
+
+ Also supports simple name search/lookup for both compound and member types.
+
+ NOTES:
+ - summary for compounds generalizes title and briefdescription because
+ there's no single field that works as a quick introduction for both
+ pages and classes
+ - May be value in eventually extending this to fulltext or levenshtein
+ distance-driven lookup/search, but I'm avoiding these for now as it
+ takes some effort to enable them.
+ */
+ "def",
+ "CREATE VIEW IF NOT EXISTS def (\n"
+ "\t-- Combined summary of all -def types for easier joins.\n"
+ "\trowid,\n"
+ "\trefid,\n"
+ "\tkind,\n"
+ "\tname,\n"
+ "\tsummary"
+ ")\n"
+ "as SELECT \n"
+ "\trefid.rowid,\n"
+ "\trefid.refid,\n"
+ "\tmemberdef.kind,\n"
+ "\tmemberdef.name,\n"
+ "\tmemberdef.briefdescription \n"
+ "FROM refid \n"
+ "JOIN memberdef ON refid.rowid=memberdef.rowid \n"
+ "UNION ALL \n"
+ "SELECT \n"
+ "\trefid.rowid,\n"
+ "\trefid.refid,\n"
+ "\tcompounddef.kind,\n"
+ "\tcompounddef.name,\n"
+ "\tCASE \n"
+ "\t\tWHEN briefdescription IS NOT NULL \n"
+ "\t\tTHEN briefdescription \n"
+ "\t\tELSE title \n"
+ "\tEND summary\n"
+ "FROM refid \n"
+ "JOIN compounddef ON refid.rowid=compounddef.rowid;"
+ },
+ {
+ "local_file",
+ "CREATE VIEW IF NOT EXISTS local_file (\n"
+ "\t-- File paths found within the project.\n"
+ "\trowid,\n"
+ "\tfound,\n"
+ "\tname\n"
+ ")\n"
+ "as SELECT \n"
+ "\tpath.rowid,\n"
+ "\tpath.found,\n"
+ "\tpath.name\n"
+ "FROM path WHERE path.type=1 AND path.local=1 AND path.found=1;\n"
+ },
+ {
+ "external_file",
+ "CREATE VIEW IF NOT EXISTS external_file (\n"
+ "\t-- File paths outside the project (found or not).\n"
+ "\trowid,\n"
+ "\tfound,\n"
+ "\tname\n"
+ ")\n"
+ "as SELECT \n"
+ "\tpath.rowid,\n"
+ "\tpath.found,\n"
+ "\tpath.name\n"
+ "FROM path WHERE path.type=1 AND path.local=0;\n"
+ },
+ {
+ "inline_xrefs",
+ "CREATE VIEW IF NOT EXISTS inline_xrefs (\n"
+ "\t-- Crossrefs from inline member source.\n"
+ "\trowid,\n"
+ "\tsrc_rowid,\n"
+ "\tdst_rowid\n"
+ ")\n"
+ "as SELECT \n"
+ "\txrefs.rowid,\n"
+ "\txrefs.src_rowid,\n"
+ "\txrefs.dst_rowid\n"
+ "FROM xrefs WHERE xrefs.context='inline';\n"
+ },
+ {
+ "argument_xrefs",
+ "CREATE VIEW IF NOT EXISTS argument_xrefs (\n"
+ "\t-- Crossrefs from member def/decl arguments\n"
+ "\trowid,\n"
+ "\tsrc_rowid,\n"
+ "\tdst_rowid\n"
+ ")\n"
+ "as SELECT \n"
+ "\txrefs.rowid,\n"
+ "\txrefs.src_rowid,\n"
+ "\txrefs.dst_rowid\n"
+ "FROM xrefs WHERE xrefs.context='argument';\n"
+ },
+ {
+ "initializer_xrefs",
+ "CREATE VIEW IF NOT EXISTS initializer_xrefs (\n"
+ "\t-- Crossrefs from member initializers\n"
+ "\trowid,\n"
+ "\tsrc_rowid,\n"
+ "\tdst_rowid\n"
+ ")\n"
+ "as SELECT \n"
+ "\txrefs.rowid,\n"
+ "\txrefs.src_rowid,\n"
+ "\txrefs.dst_rowid\n"
+ "FROM xrefs WHERE xrefs.context='initializer';\n"
+ },
+ {
+ "inner_outer",
+ "CREATE VIEW IF NOT EXISTS inner_outer\n"
+ "\t-- Joins 'contains' relations to simplify inner/outer 'rel' queries.\n"
+ "as SELECT \n"
+ "\tinner.*,\n"
+ "\touter.*\n"
+ "FROM def as inner\n"
+ "\tJOIN contains ON inner.rowid=contains.inner_rowid\n"
+ "\tJOIN def AS outer ON outer.rowid=contains.outer_rowid;\n"
+ },
+ {
+ "rel",
+ "CREATE VIEW IF NOT EXISTS rel (\n"
+ "\t-- Boolean indicator of relations available for a given entity.\n"
+ "\t-- Join to (compound-|member-)def to find fetch-worthy relations.\n"
+ "\trowid,\n"
+ "\treimplemented,\n"
+ "\treimplements,\n"
+ "\tinnercompounds,\n"
+ "\toutercompounds,\n"
+ "\tinnerpages,\n"
+ "\touterpages,\n"
+ "\tinnerdirs,\n"
+ "\touterdirs,\n"
+ "\tinnerfiles,\n"
+ "\touterfiles,\n"
+ "\tinnerclasses,\n"
+ "\touterclasses,\n"
+ "\tinnernamespaces,\n"
+ "\touternamespaces,\n"
+ "\tinnergroups,\n"
+ "\toutergroups,\n"
+ "\tmembers,\n"
+ "\tcompounds,\n"
+ "\tsubclasses,\n"
+ "\tsuperclasses,\n"
+ "\tlinks_in,\n"
+ "\tlinks_out,\n"
+ "\targument_links_in,\n"
+ "\targument_links_out,\n"
+ "\tinitializer_links_in,\n"
+ "\tinitializer_links_out\n"
+ ")\n"
+ "as SELECT \n"
+ "\tdef.rowid,\n"
+ "\tEXISTS (SELECT rowid FROM reimplements WHERE reimplemented_rowid=def.rowid),\n"
+ "\tEXISTS (SELECT rowid FROM reimplements WHERE memberdef_rowid=def.rowid),\n"
+ "\t-- rowid/kind for inner, [rowid:1/kind:1] for outer\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid),\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid),\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='page'),\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='page'),\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='dir'),\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='dir'),\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='file'),\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='file'),\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind in (\n"
+ "'category','class','enum','exception','interface','module','protocol',\n"
+ "'service','singleton','struct','type','union'\n"
+ ")),\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1] in (\n"
+ "'category','class','enum','exception','interface','module','protocol',\n"
+ "'service','singleton','struct','type','union'\n"
+ ")),\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='namespace'),\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='namespace'),\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='group'),\n"
+ "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='group'),\n"
+ "\tEXISTS (SELECT rowid FROM member WHERE scope_rowid=def.rowid),\n"
+ "\tEXISTS (SELECT rowid FROM member WHERE memberdef_rowid=def.rowid),\n"
+ "\tEXISTS (SELECT rowid FROM compoundref WHERE base_rowid=def.rowid),\n"
+ "\tEXISTS (SELECT rowid FROM compoundref WHERE derived_rowid=def.rowid),\n"
+ "\tEXISTS (SELECT rowid FROM inline_xrefs WHERE dst_rowid=def.rowid),\n"
+ "\tEXISTS (SELECT rowid FROM inline_xrefs WHERE src_rowid=def.rowid),\n"
+ "\tEXISTS (SELECT rowid FROM argument_xrefs WHERE dst_rowid=def.rowid),\n"
+ "\tEXISTS (SELECT rowid FROM argument_xrefs WHERE src_rowid=def.rowid),\n"
+ "\tEXISTS (SELECT rowid FROM initializer_xrefs WHERE dst_rowid=def.rowid),\n"
+ "\tEXISTS (SELECT rowid FROM initializer_xrefs WHERE src_rowid=def.rowid)\n"
+ "FROM def ORDER BY def.rowid;"
}
};
@@ -224,193 +506,298 @@ struct SqlStmt {
sqlite3 *db;
};
//////////////////////////////////////////////////////
-SqlStmt incl_insert = { "INSERT INTO includes "
- "( local, id_src, id_dst ) "
- "VALUES "
- "(:local,:id_src,:id_dst )"
- ,NULL
+/* If you add a new statement below, make sure to add it to
+ prepareStatements(). If sqlite3 is segfaulting (especially in
+ sqlite3_clear_bindings()), using an un-prepared statement may
+ be the cause. */
+SqlStmt meta_insert = {
+ "INSERT INTO meta "
+ "( doxygen_version, schema_version, generated_at, generated_on, project_name, project_number, project_brief )"
+ "VALUES "
+ "(:doxygen_version,:schema_version,:generated_at,:generated_on,:project_name,:project_number,:project_brief )"
+ ,NULL
+};
+//////////////////////////////////////////////////////
+SqlStmt incl_insert = {
+ "INSERT INTO includes "
+ "( local, src_id, dst_id ) "
+ "VALUES "
+ "(:local,:src_id,:dst_id )"
+ ,NULL
};
-SqlStmt incl_select = { "SELECT COUNT(*) FROM includes WHERE "
- "local=:local AND id_src=:id_src AND id_dst=:id_dst"
- ,NULL
+SqlStmt incl_select = {
+ "SELECT COUNT(*) FROM includes WHERE "
+ "local=:local AND src_id=:src_id AND dst_id=:dst_id"
+ ,NULL
};
//////////////////////////////////////////////////////
-SqlStmt innerclass_insert={"INSERT INTO innerclass "
- "( refid, prot, name )"
- "VALUES "
- "(:refid,:prot,:name )"
- ,NULL
+SqlStmt contains_insert={
+ "INSERT INTO contains "
+ "( inner_rowid, outer_rowid )"
+ "VALUES "
+ "(:inner_rowid,:outer_rowid )"
+ ,NULL
};
//////////////////////////////////////////////////////
-SqlStmt files_select = {"SELECT rowid FROM files WHERE name=:name"
+SqlStmt path_select = {
+ "SELECT rowid FROM path WHERE name=:name"
,NULL
};
-SqlStmt files_insert = {"INSERT INTO files "
- "( name )"
- "VALUES "
- "(:name )"
- ,NULL
+SqlStmt path_insert = {
+ "INSERT INTO path "
+ "( type, local, found, name )"
+ "VALUES "
+ "(:type,:local,:found,:name )"
+ ,NULL
};
//////////////////////////////////////////////////////
-SqlStmt refids_select = {"SELECT rowid FROM refids WHERE "
- "refid=:refid"
- ,NULL
+SqlStmt refid_select = {
+ "SELECT rowid FROM refid WHERE refid=:refid"
+ ,NULL
};
-SqlStmt refids_insert = {"INSERT INTO refids "
- "( refid )"
- "VALUES "
+SqlStmt refid_insert = {
+ "INSERT INTO refid "
+ "( refid )"
+ "VALUES "
"(:refid )"
- ,NULL
+ ,NULL
};
//////////////////////////////////////////////////////
-SqlStmt xrefs_insert= {"INSERT INTO xrefs "
- "( refid_src, refid_dst, id_file, line, column )"
- "VALUES "
- "(:refid_src,:refid_dst,:id_file,:line,:column )"
- ,NULL
+SqlStmt xrefs_insert= {
+ "INSERT INTO xrefs "
+ "( src_rowid, dst_rowid, context )"
+ "VALUES "
+ "(:src_rowid,:dst_rowid,:context )"
+ ,NULL
+};//////////////////////////////////////////////////////
+SqlStmt reimplements_insert= {
+ "INSERT INTO reimplements "
+ "( memberdef_rowid, reimplemented_rowid )"
+ "VALUES "
+ "(:memberdef_rowid,:reimplemented_rowid )"
+ ,NULL
};
//////////////////////////////////////////////////////
-SqlStmt memberdef_insert={"INSERT INTO memberdef "
- "("
- "refid,"
- "name,"
- "definition,"
- "type,"
- "argsstring,"
- "scope,"
- "initializer,"
- "bitfield,"
- "read,"
- "write,"
- "prot,"
- "static,"
- "const,"
- "explicit,"
- "inline,"
- "final,"
- "sealed,"
- "new,"
- "optional,"
- "required,"
- "volatile,"
- "virt,"
- "mutable,"
- "initonly,"
- "attribute,"
- "property,"
- "readonly,"
- "bound,"
- "constrained,"
- "transient,"
- "maybevoid,"
- "maybedefault,"
- "maybeambiguous,"
- "readable,"
- "writable,"
- "gettable,"
- "protectedsettable,"
- "protectedgettable,"
- "settable,"
- "privatesettable,"
- "privategettable,"
- "accessor,"
- "addable,"
- "removable,"
- "raisable,"
- "kind,"
- "bodystart,"
- "bodyend,"
- "id_bodyfile,"
- "id_file,"
- "line,"
- "column,"
- "detaileddescription,"
- "briefdescription,"
- "inbodydescription"
- ")"
- "VALUES "
- "("
- ":refid,"
- ":name,"
- ":definition,"
- ":type,"
- ":argsstring,"
- ":scope,"
- ":initializer,"
- ":bitfield,"
- ":read,"
- ":write,"
- ":prot,"
- ":static,"
- ":const,"
- ":explicit,"
- ":inline,"
- ":final,"
- ":sealed,"
- ":new,"
- ":optional,"
- ":required,"
- ":volatile,"
- ":virt,"
- ":mutable,"
- ":initonly,"
- ":attribute,"
- ":property,"
- ":readonly,"
- ":bound,"
- ":constrained,"
- ":transient,"
- ":maybevoid,"
- ":maybedefault,"
- ":maybeambiguous,"
- ":readable,"
- ":writable,"
- ":gettable,"
- ":protectedsettable,"
- ":protectedgettable,"
- ":settable,"
- ":privatesettable,"
- ":privategettable,"
- ":accessor,"
- ":addable,"
- ":removable,"
- ":raisable,"
- ":kind,"
- ":bodystart,"
- ":bodyend,"
- ":id_bodyfile,"
- ":id_file,"
- ":line,"
- ":column,"
- ":detaileddescription,"
- ":briefdescription,"
- ":inbodydescription"
- ")"
- ,NULL
+SqlStmt memberdef_exists={
+ "SELECT EXISTS (SELECT * FROM memberdef WHERE rowid = :rowid)"
+ ,NULL
+};
+
+SqlStmt memberdef_incomplete={
+ "SELECT EXISTS ("
+ "SELECT * FROM memberdef WHERE "
+ "rowid = :rowid AND inline != 2 AND inline != :new_inline"
+ ")"
+ ,NULL
+};
+
+SqlStmt memberdef_insert={
+ "INSERT INTO memberdef "
+ "("
+ "rowid,"
+ "name,"
+ "definition,"
+ "type,"
+ "argsstring,"
+ "scope,"
+ "initializer,"
+ "bitfield,"
+ "read,"
+ "write,"
+ "prot,"
+ "static,"
+ "const,"
+ "explicit,"
+ "inline,"
+ "final,"
+ "sealed,"
+ "new,"
+ "optional,"
+ "required,"
+ "volatile,"
+ "virt,"
+ "mutable,"
+ "initonly,"
+ "attribute,"
+ "property,"
+ "readonly,"
+ "bound,"
+ "constrained,"
+ "transient,"
+ "maybevoid,"
+ "maybedefault,"
+ "maybeambiguous,"
+ "readable,"
+ "writable,"
+ "gettable,"
+ "protectedsettable,"
+ "protectedgettable,"
+ "settable,"
+ "privatesettable,"
+ "privategettable,"
+ "accessor,"
+ "addable,"
+ "removable,"
+ "raisable,"
+ "kind,"
+ "bodystart,"
+ "bodyend,"
+ "bodyfile_id,"
+ "file_id,"
+ "line,"
+ "column,"
+ "detaileddescription,"
+ "briefdescription,"
+ "inbodydescription"
+ ")"
+ "VALUES "
+ "("
+ ":rowid,"
+ ":name,"
+ ":definition,"
+ ":type,"
+ ":argsstring,"
+ ":scope,"
+ ":initializer,"
+ ":bitfield,"
+ ":read,"
+ ":write,"
+ ":prot,"
+ ":static,"
+ ":const,"
+ ":explicit,"
+ ":inline,"
+ ":final,"
+ ":sealed,"
+ ":new,"
+ ":optional,"
+ ":required,"
+ ":volatile,"
+ ":virt,"
+ ":mutable,"
+ ":initonly,"
+ ":attribute,"
+ ":property,"
+ ":readonly,"
+ ":bound,"
+ ":constrained,"
+ ":transient,"
+ ":maybevoid,"
+ ":maybedefault,"
+ ":maybeambiguous,"
+ ":readable,"
+ ":writable,"
+ ":gettable,"
+ ":protectedsettable,"
+ ":protectedgettable,"
+ ":settable,"
+ ":privatesettable,"
+ ":privategettable,"
+ ":accessor,"
+ ":addable,"
+ ":removable,"
+ ":raisable,"
+ ":kind,"
+ ":bodystart,"
+ ":bodyend,"
+ ":bodyfile_id,"
+ ":file_id,"
+ ":line,"
+ ":column,"
+ ":detaileddescription,"
+ ":briefdescription,"
+ ":inbodydescription"
+ ")"
+ ,NULL
+};
+/*
+We have a slightly different need than the XML here. The XML can have two
+memberdef nodes with the same refid to document the declaration and the
+definition. This doesn't play very nice with a referential model. It isn't a
+big issue if only one is documented, but in case both are, we'll fall back on
+this kludge to combine them in a single row...
+*/
+SqlStmt memberdef_update_decl={
+ "UPDATE memberdef SET "
+ "inline = :inline,"
+ "file_id = :file_id,"
+ "line = :line,"
+ "column = :column,"
+ "detaileddescription = 'Declaration: ' || :detaileddescription || 'Definition: ' || detaileddescription,"
+ "briefdescription = 'Declaration: ' || :briefdescription || 'Definition: ' || briefdescription,"
+ "inbodydescription = 'Declaration: ' || :inbodydescription || 'Definition: ' || inbodydescription "
+ "WHERE rowid = :rowid"
+ ,NULL
+};
+SqlStmt memberdef_update_def={
+ "UPDATE memberdef SET "
+ "inline = :inline,"
+ "bodystart = :bodystart,"
+ "bodyend = :bodyend,"
+ "bodyfile_id = :bodyfile_id,"
+ "detaileddescription = 'Declaration: ' || detaileddescription || 'Definition: ' || :detaileddescription,"
+ "briefdescription = 'Declaration: ' || briefdescription || 'Definition: ' || :briefdescription,"
+ "inbodydescription = 'Declaration: ' || inbodydescription || 'Definition: ' || :inbodydescription "
+ "WHERE rowid = :rowid"
+ ,NULL
};
//////////////////////////////////////////////////////
-SqlStmt compounddef_insert={"INSERT INTO compounddef "
- "( name, kind, prot, refid, id_file, line, column ) "
- "VALUES "
- "(:name,:kind,:prot,:refid,:id_file,:line,:column )"
- ,NULL
+SqlStmt member_insert={
+ "INSERT INTO member "
+ "( scope_rowid, memberdef_rowid, prot, virt ) "
+ "VALUES "
+ "(:scope_rowid,:memberdef_rowid,:prot,:virt )"
+ ,NULL
};
//////////////////////////////////////////////////////
-SqlStmt basecompoundref_insert={"INSERT INTO basecompoundref "
- "( base, derived, refid, prot, virt ) "
- "VALUES "
- "(:base,:derived,:refid,:prot,:virt )"
- ,NULL
+SqlStmt compounddef_insert={
+ "INSERT INTO compounddef "
+ "("
+ "rowid,"
+ "name,"
+ "title,"
+ "kind,"
+ "prot,"
+ "file_id,"
+ "line,"
+ "column,"
+ "header_id,"
+ "briefdescription,"
+ "detaileddescription"
+ ")"
+ "VALUES "
+ "("
+ ":rowid,"
+ ":name,"
+ ":title,"
+ ":kind,"
+ ":prot,"
+ ":file_id,"
+ ":line,"
+ ":column,"
+ ":header_id,"
+ ":briefdescription,"
+ ":detaileddescription"
+ ")"
+ ,NULL
+};
+SqlStmt compounddef_exists={
+ "SELECT EXISTS ("
+ "SELECT * FROM compounddef WHERE rowid = :rowid"
+ ")"
+ ,NULL
};
//////////////////////////////////////////////////////
-SqlStmt derivedcompoundref_insert={"INSERT INTO derivedcompoundref "
- "( refid, prot, virt, base, derived ) "
- "VALUES "
- "(:refid,:prot,:virt,:base,:derived )"
- ,NULL
+SqlStmt compoundref_insert={
+ "INSERT INTO compoundref "
+ "( base_rowid, derived_rowid, prot, virt ) "
+ "VALUES "
+ "(:base_rowid,:derived_rowid,:prot,:virt )"
+ ,NULL
};
//////////////////////////////////////////////////////
-SqlStmt params_select = { "SELECT rowid FROM params WHERE "
+SqlStmt param_select = {
+ "SELECT rowid FROM param WHERE "
"(attributes IS NULL OR attributes=:attributes) AND "
"(type IS NULL OR type=:type) AND "
"(declname IS NULL OR declname=:declname) AND "
@@ -418,27 +805,22 @@ SqlStmt params_select = { "SELECT rowid FROM params WHERE "
"(array IS NULL OR array=:array) AND "
"(defval IS NULL OR defval=:defval) AND "
"(briefdescription IS NULL OR briefdescription=:briefdescription)"
- ,NULL
+ ,NULL
};
-SqlStmt params_insert = { "INSERT INTO params "
- "( attributes, type, declname, defname, array, defval, briefdescription ) "
- "VALUES "
+SqlStmt param_insert = {
+ "INSERT INTO param "
+ "( attributes, type, declname, defname, array, defval, briefdescription ) "
+ "VALUES "
"(:attributes,:type,:declname,:defname,:array,:defval,:briefdescription)"
- ,NULL
-};
-//////////////////////////////////////////////////////
-SqlStmt memberdef_params_insert={ "INSERT INTO memberdef_params "
- "( id_memberdef, id_param)"
- "VALUES "
- "(:id_memberdef,:id_param)"
- ,NULL
+ ,NULL
};
//////////////////////////////////////////////////////
-SqlStmt innernamespace_insert={"INSERT INTO innernamespaces "
- "( refid, name)"
- "VALUES "
- "(:refid,:name)",
- NULL
+SqlStmt memberdef_param_insert={
+ "INSERT INTO memberdef_param "
+ "( memberdef_id, param_id)"
+ "VALUES "
+ "(:memberdef_id,:param_id)"
+ ,NULL
};
@@ -491,7 +873,7 @@ static bool bindIntParameter(SqlStmt &s,const char *name,int value)
{
int idx = sqlite3_bind_parameter_index(s.stmt, name);
if (idx==0) {
- msg("sqlite3_bind_parameter_index(%s)[%s] failed: %s\n", name, s.query, sqlite3_errmsg(s.db));
+ msg("sqlite3_bind_parameter_index(%s)[%s] failed to find column: %s\n", name, s.query, sqlite3_errmsg(s.db));
return false;
}
int rv = sqlite3_bind_int(s.stmt, idx, value);
@@ -508,7 +890,7 @@ static int step(SqlStmt &s,bool getRowId=FALSE, bool select=FALSE)
int rc = sqlite3_step(s.stmt);
if (rc!=SQLITE_DONE && rc!=SQLITE_ROW)
{
- msg("sqlite3_step: %s\n", sqlite3_errmsg(s.db));
+ DBG_CTX(("sqlite3_step: %s (rc: %d)\n", sqlite3_errmsg(s.db), rc));
sqlite3_reset(s.stmt);
sqlite3_clear_bindings(s.stmt);
return -1;
@@ -520,76 +902,122 @@ static int step(SqlStmt &s,bool getRowId=FALSE, bool select=FALSE)
return rowid;
}
-static int insertFile(const char* name)
+static int insertPath(QCString name, bool local=TRUE, bool found=TRUE, int type=1)
{
int rowid=-1;
if (name==0) return rowid;
- bindTextParameter(files_select,":name",name);
- rowid=step(files_select,TRUE,TRUE);
+ name = stripFromPath(name);
+
+ bindTextParameter(path_select,":name",name.data(),FALSE);
+ rowid=step(path_select,TRUE,TRUE);
if (rowid==0)
{
- bindTextParameter(files_insert,":name",name);
- rowid=step(files_insert,TRUE);
+ bindTextParameter(path_insert,":name",name.data(),FALSE);
+ bindIntParameter(path_insert,":type",type);
+ bindIntParameter(path_insert,":local",local?1:0);
+ bindIntParameter(path_insert,":found",found?1:0);
+ rowid=step(path_insert,TRUE);
}
return rowid;
}
-static int insertRefid(const char *refid)
+static void recordMetadata()
{
- int rowid=-1;
- if (refid==0) return rowid;
+ bindTextParameter(meta_insert,":doxygen_version",versionString);
+ bindTextParameter(meta_insert,":schema_version","0.2.0"); //TODO: this should be a constant somewhere; not sure where
+ bindTextParameter(meta_insert,":generated_at",dateToString(TRUE), FALSE);
+ bindTextParameter(meta_insert,":generated_on",dateToString(FALSE), FALSE);
+ bindTextParameter(meta_insert,":project_name",Config_getString(PROJECT_NAME));
+ bindTextParameter(meta_insert,":project_number",Config_getString(PROJECT_NUMBER));
+ bindTextParameter(meta_insert,":project_brief",Config_getString(PROJECT_BRIEF));
+ step(meta_insert);
+}
- bindTextParameter(refids_select,":refid",refid);
- rowid=step(refids_select,TRUE,TRUE);
- if (rowid==0)
+struct Refid {
+ int rowid;
+ const char *refid;
+ bool created;
+};
+
+struct Refid insertRefid(const char *refid)
+{
+ struct Refid ret;
+ ret.rowid=-1;
+ ret.refid=refid;
+ ret.created = FALSE;
+ if (refid==0) return ret;
+
+ bindTextParameter(refid_select,":refid",refid);
+ ret.rowid=step(refid_select,TRUE,TRUE);
+ if (ret.rowid==0)
{
- bindTextParameter(refids_insert,":refid",refid);
- rowid=step(refids_insert,TRUE);
+ bindTextParameter(refid_insert,":refid",refid);
+ ret.rowid=step(refid_insert,TRUE);
+ ret.created = TRUE;
}
- return rowid;
+
+ return ret;
+}
+
+static bool memberdefExists(struct Refid refid)
+{
+ bindIntParameter(memberdef_exists,":rowid",refid.rowid);
+ int test = step(memberdef_exists,TRUE,TRUE);
+ return test ? true : false;
}
+static bool memberdefIncomplete(struct Refid refid, const MemberDef* md)
+{
+ bindIntParameter(memberdef_incomplete,":rowid",refid.rowid);
+ bindIntParameter(memberdef_incomplete,":new_inline",md->isInline());
+ int test = step(memberdef_incomplete,TRUE,TRUE);
+ return test ? true : false;
+}
-static bool insertMemberReference(int refid_src, int refid_dst,
- int id_file, int line, int column)
+static bool compounddefExists(struct Refid refid)
{
- if (id_file==-1||refid_src==-1||refid_dst==-1)
+ bindIntParameter(compounddef_exists,":rowid",refid.rowid);
+ int test = step(compounddef_exists,TRUE,TRUE);
+ return test ? true : false;
+}
+
+static bool insertMemberReference(struct Refid src_refid, struct Refid dst_refid, const char *context)
+{
+ if (src_refid.rowid==-1||dst_refid.rowid==-1)
return false;
if (
- !bindIntParameter(xrefs_insert,":refid_src",refid_src) ||
- !bindIntParameter(xrefs_insert,":refid_dst",refid_dst) ||
- !bindIntParameter(xrefs_insert,":id_file",id_file) ||
- !bindIntParameter(xrefs_insert,":line",line) ||
- !bindIntParameter(xrefs_insert,":column",column)
+ !bindIntParameter(xrefs_insert,":src_rowid",src_refid.rowid) ||
+ !bindIntParameter(xrefs_insert,":dst_rowid",dst_refid.rowid)
)
{
return false;
}
+ else
+ {
+ bindTextParameter(xrefs_insert,":context",context);
+ }
step(xrefs_insert);
return true;
}
-static void insertMemberReference(const MemberDef *src, const MemberDef *dst)
+static void insertMemberReference(const MemberDef *src, const MemberDef *dst, const char *context)
{
- QCString qrefid_dst = dst->getOutputFileBase() + "_1" + dst->anchor();
- QCString qrefid_src = src->getOutputFileBase() + "_1" + src->anchor();
- if (dst->getStartBodyLine()!=-1 && dst->getBodyDef())
- {
- int refid_src = insertRefid(qrefid_src.data());
- int refid_dst = insertRefid(qrefid_dst.data());
- int id_file = insertFile("no-file"); // TODO: replace no-file with proper file
- insertMemberReference(refid_src,refid_dst,id_file,dst->getStartBodyLine(),-1);
- }
+ QCString qdst_refid = dst->getOutputFileBase() + "_1" + dst->anchor();
+ QCString qsrc_refid = src->getOutputFileBase() + "_1" + src->anchor();
+
+ struct Refid src_refid = insertRefid(qsrc_refid);
+ struct Refid dst_refid = insertRefid(qdst_refid);
+ insertMemberReference(src_refid,dst_refid,context);
}
-static void insertMemberFunctionParams(int id_memberdef, const MemberDef *md, const Definition *def)
+static void insertMemberFunctionParams(int memberdef_id, const MemberDef *md, const Definition *def)
{
ArgumentList *declAl = md->declArgumentList();
ArgumentList *defAl = md->argumentList();
- if (declAl!=0 && declAl->count()>0)
+ if (declAl!=0 && defAl!=0 && declAl->count()>0)
{
ArgumentListIterator declAli(*declAl);
ArgumentListIterator defAli(*defAl);
@@ -600,8 +1028,8 @@ static void insertMemberFunctionParams(int id_memberdef, const MemberDef *md, co
if (!a->attrib.isEmpty())
{
- bindTextParameter(params_select,":attributes",a->attrib.data());
- bindTextParameter(params_insert,":attributes",a->attrib.data());
+ bindTextParameter(param_select,":attributes",a->attrib);
+ bindTextParameter(param_insert,":attributes",a->attrib);
}
if (!a->type.isEmpty())
{
@@ -612,57 +1040,56 @@ static void insertMemberFunctionParams(int id_memberdef, const MemberDef *md, co
QCString *s;
while ((s=li.current()))
{
- QCString qrefid_src = md->getOutputFileBase() + "_1" + md->anchor();
- int refid_src = insertRefid(qrefid_src.data());
- int refid_dst = insertRefid(s->data());
- int id_file = insertFile(stripFromPath(def->getDefFileName()));
- insertMemberReference(refid_src,refid_dst,id_file,md->getDefLine(),-1);
+ QCString qsrc_refid = md->getOutputFileBase() + "_1" + md->anchor();
+ struct Refid src_refid = insertRefid(qsrc_refid);
+ struct Refid dst_refid = insertRefid(s->data());
+ insertMemberReference(src_refid,dst_refid, "argument");
++li;
}
- bindTextParameter(params_select,":type",a->type.data());
- bindTextParameter(params_insert,":type",a->type.data());
+ bindTextParameter(param_select,":type",a->type);
+ bindTextParameter(param_insert,":type",a->type);
}
if (!a->name.isEmpty())
{
- bindTextParameter(params_select,":declname",a->name.data());
- bindTextParameter(params_insert,":declname",a->name.data());
+ bindTextParameter(param_select,":declname",a->name);
+ bindTextParameter(param_insert,":declname",a->name);
}
if (defArg && !defArg->name.isEmpty() && defArg->name!=a->name)
{
- bindTextParameter(params_select,":defname",defArg->name.data());
- bindTextParameter(params_insert,":defname",defArg->name.data());
+ bindTextParameter(param_select,":defname",defArg->name);
+ bindTextParameter(param_insert,":defname",defArg->name);
}
if (!a->array.isEmpty())
{
- bindTextParameter(params_select,":array",a->array.data());
- bindTextParameter(params_insert,":array",a->array.data());
+ bindTextParameter(param_select,":array",a->array);
+ bindTextParameter(param_insert,":array",a->array);
}
if (!a->defval.isEmpty())
{
StringList l;
linkifyText(TextGeneratorSqlite3Impl(l),def,md->getBodyDef(),md,a->defval);
- bindTextParameter(params_select,":defval",a->defval.data());
- bindTextParameter(params_insert,":defval",a->defval.data());
+ bindTextParameter(param_select,":defval",a->defval);
+ bindTextParameter(param_insert,":defval",a->defval);
}
if (defArg) ++defAli;
- int id_param=step(params_select,TRUE,TRUE);
- if (id_param==0) {
- id_param=step(params_insert,TRUE);
+ int param_id=step(param_select,TRUE,TRUE);
+ if (param_id==0) {
+ param_id=step(param_insert,TRUE);
}
- if (id_param==-1) {
- msg("error INSERT params failed\n");
+ if (param_id==-1) {
+ DBG_CTX(("error INSERT params failed\n"));
continue;
}
- bindIntParameter(memberdef_params_insert,":id_memberdef",id_memberdef);
- bindIntParameter(memberdef_params_insert,":id_param",id_param);
- step(memberdef_params_insert);
+ bindIntParameter(memberdef_param_insert,":memberdef_id",memberdef_id);
+ bindIntParameter(memberdef_param_insert,":param_id",param_id);
+ step(memberdef_param_insert);
}
}
}
-static void insertMemberDefineParams(int id_memberdef,const MemberDef *md, const Definition *def)
+static void insertMemberDefineParams(int memberdef_id,const MemberDef *md, const Definition *def)
{
if (md->argumentList()->count()==0) // special case for "foo()" to
// disguish it from "foo".
@@ -675,20 +1102,34 @@ static void insertMemberDefineParams(int id_memberdef,const MemberDef *md, const
Argument *a;
for (ali.toFirst();(a=ali.current());++ali)
{
- bindTextParameter(params_insert,":defname",a->type.data());
- int id_param=step(params_insert,TRUE);
- if (id_param==-1) {
- msg("error INSERT param(%s) failed\n", a->type.data());
+ bindTextParameter(param_insert,":defname",a->type);
+ int param_id=step(param_insert,TRUE);
+ if (param_id==-1) {
continue;
}
- bindIntParameter(memberdef_params_insert,":id_memberdef",id_memberdef);
- bindIntParameter(memberdef_params_insert,":id_param",id_param);
- step(memberdef_params_insert);
+ bindIntParameter(memberdef_param_insert,":memberdef_id",memberdef_id);
+ bindIntParameter(memberdef_param_insert,":param_id",param_id);
+ step(memberdef_param_insert);
}
}
}
+static void associateMember(const MemberDef *md, struct Refid member_refid, struct Refid scope_refid)
+{
+ // TODO: skip EnumValue only to guard against recording refids and member records
+ // for enumvalues until we can support documenting them as entities.
+ if (md->memberType()==MemberType_EnumValue) return;
+ if (md->name().at(0)!='@') // skip anonymous members
+ {
+ bindIntParameter(member_insert, ":scope_rowid", scope_refid.rowid);
+ bindIntParameter(member_insert, ":memberdef_rowid", member_refid.rowid);
+
+ bindIntParameter(member_insert, ":prot", md->protection());
+ bindIntParameter(member_insert, ":virt", md->virtualness());
+ step(member_insert);
+ }
+}
static void stripQualifiers(QCString &typeStr)
{
@@ -720,22 +1161,28 @@ static int prepareStatement(sqlite3 *db, SqlStmt &s)
static int prepareStatements(sqlite3 *db)
{
if (
+ -1==prepareStatement(db, meta_insert) ||
+ -1==prepareStatement(db, memberdef_exists) ||
+ -1==prepareStatement(db, memberdef_incomplete) ||
-1==prepareStatement(db, memberdef_insert) ||
- -1==prepareStatement(db, files_insert) ||
- -1==prepareStatement(db, files_select) ||
- -1==prepareStatement(db, refids_insert) ||
- -1==prepareStatement(db, refids_select) ||
+ -1==prepareStatement(db, memberdef_update_def) ||
+ -1==prepareStatement(db, memberdef_update_decl) ||
+ -1==prepareStatement(db, member_insert) ||
+ -1==prepareStatement(db, path_insert) ||
+ -1==prepareStatement(db, path_select) ||
+ -1==prepareStatement(db, refid_insert) ||
+ -1==prepareStatement(db, refid_select) ||
-1==prepareStatement(db, incl_insert)||
-1==prepareStatement(db, incl_select)||
- -1==prepareStatement(db, params_insert) ||
- -1==prepareStatement(db, params_select) ||
+ -1==prepareStatement(db, param_insert) ||
+ -1==prepareStatement(db, param_select) ||
-1==prepareStatement(db, xrefs_insert) ||
- -1==prepareStatement(db, innerclass_insert) ||
+ -1==prepareStatement(db, reimplements_insert) ||
+ -1==prepareStatement(db, contains_insert) ||
+ -1==prepareStatement(db, compounddef_exists) ||
-1==prepareStatement(db, compounddef_insert) ||
- -1==prepareStatement(db, basecompoundref_insert) ||
- -1==prepareStatement(db, derivedcompoundref_insert) ||
- -1==prepareStatement(db, memberdef_params_insert)||
- -1==prepareStatement(db, innernamespace_insert)
+ -1==prepareStatement(db, compoundref_insert) ||
+ -1==prepareStatement(db, memberdef_param_insert)
)
{
return -1;
@@ -763,15 +1210,35 @@ static void pragmaTuning(sqlite3 *db)
sqlite3_exec(db, "PRAGMA temp_store = MEMORY;", NULL, NULL, &sErrMsg);
}
-static int initializeSchema(sqlite3* db)
+static int initializeTables(sqlite3* db)
+{
+ int rc;
+ sqlite3_stmt *stmt = 0;
+
+ msg("Initializing DB schema (tables)...\n");
+ for (unsigned int k = 0; k < sizeof(table_schema) / sizeof(table_schema[0]); k++)
+ {
+ const char *q = table_schema[k][1];
+ char *errmsg;
+ rc = sqlite3_exec(db, q, NULL, NULL, &errmsg);
+ if (rc != SQLITE_OK)
+ {
+ msg("failed to execute query: %s\n\t%s\n", q, errmsg);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int initializeViews(sqlite3* db)
{
int rc;
sqlite3_stmt *stmt = 0;
- msg("Initializing DB schema...\n");
- for (unsigned int k = 0; k < sizeof(schema_queries) / sizeof(schema_queries[0]); k++)
+ msg("Initializing DB schema (views)...\n");
+ for (unsigned int k = 0; k < sizeof(view_schema) / sizeof(view_schema[0]); k++)
{
- const char *q = schema_queries[k][1];
+ const char *q = view_schema[k][1];
char *errmsg;
rc = sqlite3_exec(db, q, NULL, NULL, &errmsg);
if (rc != SQLITE_OK)
@@ -784,40 +1251,122 @@ static int initializeSchema(sqlite3* db)
}
////////////////////////////////////////////
-static void writeInnerClasses(const ClassSDict *cl)
+/* TODO:
+I collapsed all innerX tables into 'contains', which raises the prospect that
+all of these very similar writeInnerX funcs could be refactored into a one,
+or a small set of common parts.
+
+I think the hurdles are:
+- picking a first argument that every call location can pass
+- which yields a consistent iterator
+- accommodates PageDef's slightly different rules for generating the
+ inner_refid (unless I'm missing a method that would uniformly return
+ the correct refid for all types).
+*/
+static void writeInnerClasses(const ClassSDict *cl, struct Refid outer_refid)
{
if (!cl) return;
ClassSDict::Iterator cli(*cl);
- ClassDef *cd;
+ const ClassDef *cd;
for (cli.toFirst();(cd=cli.current());++cli)
{
if (!cd->isHidden() && cd->name().find('@')==-1) // skip anonymous scopes
{
- int refid = insertRefid(cd->getOutputFileBase());
- bindIntParameter(innerclass_insert,":refid", refid);
- bindIntParameter(innerclass_insert,":prot",cd->protection());
- bindTextParameter(innerclass_insert,":name",cd->name());
- step(innerclass_insert);
+ struct Refid inner_refid = insertRefid(cd->getOutputFileBase());
+
+ bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid);
+ bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid);
+ step(contains_insert);
}
}
}
+static void writeInnerPages(const PageSDict *pl, struct Refid outer_refid)
+{
+ if (!pl) return;
+
+ PageSDict::Iterator pli(*pl);
+ const PageDef *pd;
+ for (pli.toFirst();(pd=pli.current());++pli)
+ {
+ struct Refid inner_refid = insertRefid(
+ pd->getGroupDef() ? pd->getOutputFileBase()+"_"+pd->name() : pd->getOutputFileBase()
+ );
+
+ bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid);
+ bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid);
+ step(contains_insert);
-static void writeInnerNamespaces(const NamespaceSDict *nl)
+ }
+}
+
+static void writeInnerGroups(const GroupList *gl, struct Refid outer_refid)
+{
+ if (gl)
+ {
+ GroupListIterator gli(*gl);
+ const GroupDef *sgd;
+ for (gli.toFirst();(sgd=gli.current());++gli)
+ {
+ struct Refid inner_refid = insertRefid(sgd->getOutputFileBase());
+
+ bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid);
+ bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid);
+ step(contains_insert);
+ }
+ }
+}
+
+static void writeInnerFiles(const FileList *fl, struct Refid outer_refid)
+{
+ if (fl)
+ {
+ QListIterator<FileDef> fli(*fl);
+ const FileDef *fd;
+ for (fli.toFirst();(fd=fli.current());++fli)
+ {
+ struct Refid inner_refid = insertRefid(fd->getOutputFileBase());
+
+ bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid);
+ bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid);
+ step(contains_insert);
+ }
+ }
+}
+
+static void writeInnerDirs(const DirList *dl, struct Refid outer_refid)
+{
+ if (dl)
+ {
+ QListIterator<DirDef> subdirs(*dl);
+ const DirDef *subdir;
+ for (subdirs.toFirst();(subdir=subdirs.current());++subdirs)
+ {
+ struct Refid inner_refid = insertRefid(subdir->getOutputFileBase());
+
+ bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid);
+ bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid);
+ step(contains_insert);
+ }
+ }
+}
+
+static void writeInnerNamespaces(const NamespaceSDict *nl, struct Refid outer_refid)
{
if (nl)
{
NamespaceSDict::Iterator nli(*nl);
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (nli.toFirst();(nd=nli.current());++nli)
{
- if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymouse scopes
+ if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymous scopes
{
- int refid = insertRefid(nd->getOutputFileBase());
- bindIntParameter(innernamespace_insert,":refid",refid);
- bindTextParameter(innernamespace_insert,":name",nd->name(),FALSE);
- step(innernamespace_insert);
+ struct Refid inner_refid = insertRefid(nd->getOutputFileBase());
+
+ bindIntParameter(contains_insert,":inner_rowid",inner_refid.rowid);
+ bindIntParameter(contains_insert,":outer_rowid",outer_refid.rowid);
+ step(contains_insert);
}
}
}
@@ -837,24 +1386,24 @@ static void writeTemplateArgumentList(const ArgumentList * al,
if (!a->type.isEmpty())
{
#warning linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->type);
- bindTextParameter(params_select,":type",a->type);
- bindTextParameter(params_insert,":type",a->type);
+ bindTextParameter(param_select,":type",a->type);
+ bindTextParameter(param_insert,":type",a->type);
}
if (!a->name.isEmpty())
{
- bindTextParameter(params_select,":declname",a->name);
- bindTextParameter(params_insert,":declname",a->name);
- bindTextParameter(params_select,":defname",a->name);
- bindTextParameter(params_insert,":defname",a->name);
+ bindTextParameter(param_select,":declname",a->name);
+ bindTextParameter(param_insert,":declname",a->name);
+ bindTextParameter(param_select,":defname",a->name);
+ bindTextParameter(param_insert,":defname",a->name);
}
if (!a->defval.isEmpty())
{
#warning linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->defval);
- bindTextParameter(params_select,":defval",a->defval);
- bindTextParameter(params_insert,":defval",a->defval);
+ bindTextParameter(param_select,":defval",a->defval);
+ bindTextParameter(param_insert,":defval",a->defval);
}
- if (!step(params_select,TRUE,TRUE))
- step(params_insert);
+ if (!step(param_select,TRUE,TRUE))
+ step(param_insert);
}
}
}
@@ -871,15 +1420,132 @@ static void writeTemplateList(const ClassDef *cd)
{
writeTemplateArgumentList(cd->templateArguments(),cd,0);
}
+
+QCString getSQLDocBlock(const Definition *scope,
+ const Definition *def,
+ const QCString &doc,
+ const QCString &fileName,
+ int lineNr)
+{
+ QGString s;
+ if (doc.isEmpty()) return s.data();
+ FTextStream t(&s);
+ DocNode *root = validatingParseDoc(
+ fileName,
+ lineNr,
+ const_cast<Definition*>(scope),
+ const_cast<MemberDef*>(reinterpret_cast<const MemberDef*>(def)),
+ doc,
+ FALSE,
+ FALSE
+ );
+ XMLCodeGenerator codeGen(t);
+ // create a parse tree visitor for XML
+ XmlDocVisitor *visitor = new XmlDocVisitor(t,codeGen);
+ root->accept(visitor);
+ delete visitor;
+ delete root;
+ QCString result = convertCharEntitiesToUTF8(s.data());
+ return result.data();
+}
+
+static void getSQLDesc(SqlStmt &s,const char *col,const char *value,const Definition *def)
+{
+ bindTextParameter(
+ s,
+ col,
+ getSQLDocBlock(
+ def->getOuterScope(),
+ def,
+ value,
+ def->docFile(),
+ def->docLine()
+ ),
+ FALSE
+ );
+}
////////////////////////////////////////////
+/* (updated Sep 01 2018)
+DoxMemberKind and DoxCompoundKind (compound.xsd) gave me some
+faulty assumptions about "kind" strings, so I compiled a reference
+
+The XML schema claims:
+ DoxMemberKind: (14)
+ dcop define enum event friend function interface property prototype
+ service signal slot typedef variable
+
+ DoxCompoundKind: (17)
+ category class dir example exception file group interface module
+ namespace page protocol service singleton struct type union
+
+Member kind comes from MemberDef::memberTypeName()
+ types.h defines 14 MemberType_*s
+ _DCOP _Define _Enumeration _EnumValue _Event _Friend _Function _Interface
+ _Property _Service _Signal _Slot _Typedef _Variable
+ - xml doesn't include enumvalue here
+ (but renders enumvalue as) a sub-node of memberdef/templateparamlist
+ - xml includes 'prototype' that is unlisted here
+ vestigial? commented out in docsets.cpp and perlmodgen.cpp
+ MemberDef::memberTypeName() can return 15 strings:
+ (sorted by MemberType to match above; quoted because whitespace...)
+ "dcop" "macro definition" "enumeration" "enumvalue" "event" "friend"
+ "function" "interface" "property" "service" "signal" "slot" "typedef"
+ "variable"
+
+ Above describes potential values for memberdef.kind
+
+Compound kind is more complex. *Def::compoundTypeString()
+ ClassDef kind comes from ::compoundTypeString()
+ classdef.h defines 9 compound types
+ Category Class Exception Interface Protocol Service Singleton Struct Union
+ But ClassDef::compoundTypeString() "could" return 13 strings
+ - default "unknown" shouldn't actually return
+ - other 12 can vary by source language; see method for specifics
+ category class enum exception interface module protocol service
+ singleton struct type union
+
+ DirDef, FileDef, GroupDef have no method to return a string
+ tagfile/outputs hard-code kind to 'dir' 'file' or 'group'
+
+ NamespaceDef kind comes from ::compoundTypeString()
+ NamespaceDef::compoundTypeString() "could" return 6 strings
+ - default empty ("") string
+ - other 5 differ by source language
+ constants library module namespace package
+
+ PageDef also has no method to return a string
+ - some locations hard-code the kind to 'page'
+ - others conditionally output 'page' or 'example'
+
+ All together, that's 23 potential strings (21 excl "" and unknown)
+ "" category class constants dir enum example exception file group
+ interface library module namespace package page protocol service singleton
+ struct type union unknown
+
+ Above describes potential values for compounddef.kind
+
+For reference, there are 35 potential values of def.kind (33 excl "" and unknown):
+ "" "category" "class" "constants" "dcop" "dir" "enum" "enumeration"
+ "enumvalue" "event" "example" "exception" "file" "friend" "function" "group"
+ "interface" "library" "macro definition" "module" "namespace" "package"
+ "page" "property" "protocol" "service" "signal" "singleton" "slot" "struct"
+ "type" "typedef" "union" "unknown" "variable"
+
+This is relevant because the 'def' view generalizes memberdef and compounddef,
+and two member+compound kind strings (interface and service) overlap.
+
+I have no grasp of whether a real user docset would include one or more
+member and compound using the interface or service kind.
+*/
+
//////////////////////////////////////////////////////////////////////////////
-static void generateSqlite3ForMember(const MemberDef *md, const Definition *def)
+static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_refid, const Definition *def)
{
// + declaration/definition arg lists
// + reimplements
// + reimplementedBy
- // + exceptions
+ // - exceptions
// + const/volatile specifiers
// - examples
// + source definition
@@ -893,18 +1559,102 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def)
// enum values are written as part of the enum
if (md->memberType()==MemberType_EnumValue) return;
if (md->isHidden()) return;
- //if (md->name().at(0)=='@') return; // anonymous member
- // group members are only visible in their group
- //if (def->definitionType()!=Definition::TypeGroup && md->getGroupDef()) return;
QCString memType;
// memberdef
QCString qrefid = md->getOutputFileBase() + "_1" + md->anchor();
- int refid = insertRefid(qrefid.data());
+ struct Refid refid = insertRefid(qrefid);
+
+ associateMember(md, refid, scope_refid);
+
+ // compacting duplicate defs
+ if(!refid.created && memberdefExists(refid) && memberdefIncomplete(refid, md))
+ {
+ /*
+ For performance, ideal to skip a member we've already added.
+ Unfortunately, we can have two memberdefs with the same refid documenting
+ the declaration and definition. memberdefIncomplete() uses the 'inline'
+ value to figure this out. Once we get to this point, we should *only* be
+ seeing the *other* type of def/decl, so we'll set inline to a new value (2),
+ indicating that this entry covers both inline types.
+ */
+ struct SqlStmt memberdef_update;
+
+ // definitions have bodyfile/start/end
+ if (md->getStartBodyLine()!=-1)
+ {
+ memberdef_update = memberdef_update_def;
+ int bodyfile_id = insertPath(md->getBodyDef()->absFilePath(),!md->getBodyDef()->isReference());
+ if (bodyfile_id == -1)
+ {
+ sqlite3_clear_bindings(memberdef_update.stmt);
+ }
+ else
+ {
+ bindIntParameter(memberdef_update,":bodyfile_id",bodyfile_id);
+ bindIntParameter(memberdef_update,":bodystart",md->getStartBodyLine());
+ bindIntParameter(memberdef_update,":bodyend",md->getEndBodyLine());
+ }
+ }
+ // declarations don't
+ else
+ {
+ memberdef_update = memberdef_update_decl;
+ if (md->getDefLine() != -1)
+ {
+ int file_id = insertPath(md->getDefFileName(),!md->isReference());
+ if (file_id!=-1)
+ {
+ bindIntParameter(memberdef_update,":file_id",file_id);
+ bindIntParameter(memberdef_update,":line",md->getDefLine());
+ bindIntParameter(memberdef_update,":column",md->getDefColumn());
+ }
+ }
+ }
- bindIntParameter(memberdef_insert,":refid", refid);
- bindIntParameter(memberdef_insert,":kind",md->memberType());
+ bindIntParameter(memberdef_update, ":rowid", refid.rowid);
+ // value 2 indicates we've seen "both" inline types.
+ bindIntParameter(memberdef_update,":inline", 2);
+
+ /* in case both are used, append/prepend descriptions */
+ getSQLDesc(memberdef_update,":briefdescription",md->briefDescription(),md);
+ getSQLDesc(memberdef_update,":detaileddescription",md->documentation(),md);
+ getSQLDesc(memberdef_update,":inbodydescription",md->inbodyDocumentation(),md);
+
+ step(memberdef_update,TRUE);
+
+ // don't think we need to repeat params; should have from first encounter
+
+ // + source references
+ // The cross-references in initializers only work when both the src and dst
+ // are defined.
+ MemberSDict *mdict = md->getReferencesMembers();
+ if (mdict!=0)
+ {
+ MemberSDict::IteratorDict mdi(*mdict);
+ const MemberDef *rmd;
+ for (mdi.toFirst();(rmd=mdi.current());++mdi)
+ {
+ insertMemberReference(md,rmd, "inline");
+ }
+ }
+ // + source referenced by
+ mdict = md->getReferencedByMembers();
+ if (mdict!=0)
+ {
+ MemberSDict::IteratorDict mdi(*mdict);
+ const MemberDef *rmd;
+ for (mdi.toFirst();(rmd=mdi.current());++mdi)
+ {
+ insertMemberReference(rmd,md, "inline");
+ }
+ }
+ return;
+ }
+
+ bindIntParameter(memberdef_insert,":rowid", refid.rowid);
+ bindTextParameter(memberdef_insert,":kind",md->memberTypeName(),FALSE);
bindIntParameter(memberdef_insert,":prot",md->protection());
bindIntParameter(memberdef_insert,":static",md->isStatic());
@@ -973,6 +1723,7 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def)
bindIntParameter(memberdef_insert,":settable",md->isSettable());
bindIntParameter(memberdef_insert,":privatesettable",md->isPrivateSettable());
bindIntParameter(memberdef_insert,":protectedsettable",md->isProtectedSettable());
+
if (md->isAssign() || md->isCopy() || md->isRetain()
|| md->isStrong() || md->isWeak())
{
@@ -995,6 +1746,18 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def)
bindIntParameter(memberdef_insert,":raisable",md->isRaisable());
}
+ const MemberDef *rmd = md->reimplements();
+ if(rmd)
+ {
+ QCString qreimplemented_refid = rmd->getOutputFileBase() + "_1" + rmd->anchor();
+
+ struct Refid reimplemented_refid = insertRefid(qreimplemented_refid);
+
+ bindIntParameter(reimplements_insert,":memberdef_rowid", refid.rowid);
+ bindIntParameter(reimplements_insert,":reimplemented_rowid", reimplemented_refid.rowid);
+ step(reimplements_insert,TRUE);
+ }
+
// + declaration/definition arg lists
if (md->memberType()!=MemberType_Define &&
md->memberType()!=MemberType_Enumeration
@@ -1008,9 +1771,9 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def)
stripQualifiers(typeStr);
StringList l;
linkifyText(TextGeneratorSqlite3Impl(l), def, md->getBodyDef(),md,typeStr);
- if (typeStr.data())
+ if (typeStr)
{
- bindTextParameter(memberdef_insert,":type",typeStr.data(),FALSE);
+ bindTextParameter(memberdef_insert,":type",typeStr,FALSE);
}
if (md->definition())
@@ -1029,7 +1792,7 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def)
// Extract references from initializer
if (md->hasMultiLineInitializer() || md->hasOneLineInitializer())
{
- bindTextParameter(memberdef_insert,":initializer",md->initializer().data());
+ bindTextParameter(memberdef_insert,":initializer",md->initializer());
StringList l;
linkifyText(TextGeneratorSqlite3Impl(l),def,md->getBodyDef(),md,md->initializer());
@@ -1044,11 +1807,10 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def)
s->data(),
md->getBodyDef()->getDefFileName().data(),
md->getStartBodyLine()));
- QCString qrefid_src = md->getOutputFileBase() + "_1" + md->anchor();
- int refid_src = insertRefid(qrefid_src.data());
- int refid_dst = insertRefid(s->data());
- int id_file = insertFile(stripFromPath(md->getBodyDef()->getDefFileName()));
- insertMemberReference(refid_src,refid_dst,id_file,md->getStartBodyLine(),-1);
+ QCString qsrc_refid = md->getOutputFileBase() + "_1" + md->anchor();
+ struct Refid src_refid = insertRefid(qsrc_refid);
+ struct Refid dst_refid = insertRefid(s->data());
+ insertMemberReference(src_refid,dst_refid, "initializer");
}
++li;
}
@@ -1056,34 +1818,35 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def)
if ( md->getScopeString() )
{
- bindTextParameter(memberdef_insert,":scope",md->getScopeString().data(),FALSE);
+ bindTextParameter(memberdef_insert,":scope",md->getScopeString(),FALSE);
}
// +Brief, detailed and inbody description
- bindTextParameter(memberdef_insert,":briefdescription",md->briefDescription(),FALSE);
- bindTextParameter(memberdef_insert,":detaileddescription",md->documentation(),FALSE);
- bindTextParameter(memberdef_insert,":inbodydescription",md->inbodyDocumentation(),FALSE);
+ getSQLDesc(memberdef_insert,":briefdescription",md->briefDescription(),md);
+ getSQLDesc(memberdef_insert,":detaileddescription",md->documentation(),md);
+ getSQLDesc(memberdef_insert,":inbodydescription",md->inbodyDocumentation(),md);
// File location
if (md->getDefLine() != -1)
{
- int id_file = insertFile(stripFromPath(md->getDefFileName()));
- if (id_file!=-1)
+ int file_id = insertPath(md->getDefFileName(),!md->isReference());
+ if (file_id!=-1)
{
- bindIntParameter(memberdef_insert,":id_file",id_file);
+ bindIntParameter(memberdef_insert,":file_id",file_id);
bindIntParameter(memberdef_insert,":line",md->getDefLine());
bindIntParameter(memberdef_insert,":column",md->getDefColumn());
+ // definitions also have bodyfile/start/end
if (md->getStartBodyLine()!=-1)
{
- int id_bodyfile = insertFile(stripFromPath(md->getBodyDef()->absFilePath()));
- if (id_bodyfile == -1)
+ int bodyfile_id = insertPath(md->getBodyDef()->absFilePath(),!md->getBodyDef()->isReference());
+ if (bodyfile_id == -1)
{
sqlite3_clear_bindings(memberdef_insert.stmt);
}
else
{
- bindIntParameter(memberdef_insert,":id_bodyfile",id_bodyfile);
+ bindIntParameter(memberdef_insert,":bodyfile_id",bodyfile_id);
bindIntParameter(memberdef_insert,":bodystart",md->getStartBodyLine());
bindIntParameter(memberdef_insert,":bodyend",md->getEndBodyLine());
}
@@ -1091,16 +1854,16 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def)
}
}
- int id_memberdef=step(memberdef_insert,TRUE);
+ int memberdef_id=step(memberdef_insert,TRUE);
if (isFunc)
{
- insertMemberFunctionParams(id_memberdef,md,def);
+ insertMemberFunctionParams(memberdef_id,md,def);
}
else if (md->memberType()==MemberType_Define &&
md->argsString())
{
- insertMemberDefineParams(id_memberdef,md,def);
+ insertMemberDefineParams(memberdef_id,md,def);
}
// + source references
@@ -1110,10 +1873,10 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def)
if (mdict!=0)
{
MemberSDict::IteratorDict mdi(*mdict);
- MemberDef *rmd;
+ const MemberDef *rmd;
for (mdi.toFirst();(rmd=mdi.current());++mdi)
{
- insertMemberReference(md,rmd);//,mdi.currentKey());
+ insertMemberReference(md,rmd, "inline");
}
}
// + source referenced by
@@ -1121,62 +1884,79 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def)
if (mdict!=0)
{
MemberSDict::IteratorDict mdi(*mdict);
- MemberDef *rmd;
+ const MemberDef *rmd;
for (mdi.toFirst();(rmd=mdi.current());++mdi)
{
- insertMemberReference(rmd,md);//,mdi.currentKey());
+ insertMemberReference(rmd,md, "inline");
}
}
}
static void generateSqlite3Section( const Definition *d,
const MemberList *ml,
+ struct Refid scope_refid,
const char * /*kind*/,
const char * /*header*/=0,
const char * /*documentation*/=0)
{
if (ml==0) return;
MemberListIterator mli(*ml);
- MemberDef *md;
- int count=0;
+ const MemberDef *md;
+
for (mli.toFirst();(md=mli.current());++mli)
{
+ // TODO: necessary? just tracking what xmlgen does; xmlgen says:
// namespace members are also inserted in the file scope, but
// to prevent this duplication in the XML output, we filter those here.
if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0)
{
- count++;
+ generateSqlite3ForMember(md, scope_refid, d);
}
}
- if (count==0) return; // empty list
- for (mli.toFirst();(md=mli.current());++mli)
+}
+
+static void associateAllClassMembers(const ClassDef *cd, struct Refid scope_refid)
+{
+ if (cd->memberNameInfoSDict())
{
- // namespace members are also inserted in the file scope, but
- // to prevent this duplication in the XML output, we filter those here.
- //if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0)
+ MemberNameInfoSDict::Iterator mnii(*cd->memberNameInfoSDict());
+ MemberNameInfo *mni;
+ for (mnii.toFirst();(mni=mnii.current());++mnii)
{
- generateSqlite3ForMember(md,d);
+ MemberNameInfoIterator mii(*mni);
+ MemberInfo *mi;
+ for (mii.toFirst();(mi=mii.current());++mii)
+ {
+ MemberDef *md = mi->memberDef;
+ QCString qrefid = md->getOutputFileBase() + "_1" + md->anchor();
+ associateMember(md, insertRefid(qrefid), scope_refid);
+ }
}
}
}
-
+// many kinds: category class enum exception interface
+// module protocol service singleton struct type union
+// enum is Java only (and is distinct from enum memberdefs)
static void generateSqlite3ForClass(const ClassDef *cd)
{
+ // NOTE: Skeptical about XML's version of these
+ // 'x' marks missing items XML claims to include
+
+ // + brief description
+ // + detailed description
+ // + template argument list(s)
+ // + include file
+ // + member groups
+ // x inheritance DOT diagram
// + list of direct super classes
// + list of direct sub classes
- // + include file
// + list of inner classes
- // - template argument list(s)
- // + member groups
+ // x collaboration DOT diagram
// + list of all members
- // - brief description
- // - detailed description
- // - inheritance DOT diagram
- // - collaboration DOT diagram
- // - user defined member sections
- // - standard member sections
- // - detailed member documentation
+ // x user defined member sections
+ // x standard member sections
+ // x detailed member documentation
// - examples using the class
if (cd->isReference()) return; // skip external references.
@@ -1184,43 +1964,86 @@ static void generateSqlite3ForClass(const ClassDef *cd)
if (cd->name().find('@')!=-1) return; // skip anonymous compounds.
if (cd->templateMaster()!=0) return; // skip generated template instances.
- msg("Generating Sqlite3 output for class %s\n",cd->name().data());
+ struct Refid refid = insertRefid(cd->getOutputFileBase());
+
+ // can omit a class that already has a refid
+ if(!refid.created && compounddefExists(refid)){return;}
+
+ bindIntParameter(compounddef_insert,":rowid", refid.rowid);
bindTextParameter(compounddef_insert,":name",cd->name());
+ bindTextParameter(compounddef_insert,":title",cd->title(), FALSE);
bindTextParameter(compounddef_insert,":kind",cd->compoundTypeString(),FALSE);
bindIntParameter(compounddef_insert,":prot",cd->protection());
- int refid = insertRefid(cd->getOutputFileBase());
- bindIntParameter(compounddef_insert,":refid", refid);
- int id_file = insertFile(stripFromPath(cd->getDefFileName()));
- bindIntParameter(compounddef_insert,":id_file",id_file);
+ int file_id = insertPath(cd->getDefFileName());
+ bindIntParameter(compounddef_insert,":file_id",file_id);
bindIntParameter(compounddef_insert,":line",cd->getDefLine());
bindIntParameter(compounddef_insert,":column",cd->getDefColumn());
+ // + include file
+ /*
+ TODO: I wonder if this can actually be cut (just here)
+
+ We were adding this "include" to the "includes" table alongside
+ other includes (from a FileDef). However, FileDef and ClassDef are using
+ "includes" nodes in very a different way:
+ - With FileDef, it means the file includes another.
+ - With ClassDef, it means you should include this file to use this class.
+
+ Because of this difference, I added a column to compounddef, header_id, and
+ linked it back to the appropriate file. We could just add a nullable text
+ column that would hold a string equivalent to what the HTML docs include,
+ but the logic for generating it is embedded in
+ ClassDef::writeIncludeFiles(OutputList &ol).
+
+ That said, at least on the handful of test sets I have, header_id == file_id,
+ suggesting it could be cut and clients might be able to reconstruct it from
+ other values if there's a solid heuristic for *when a class will
+ have a header file*.
+ */
+ IncludeInfo *ii=cd->includeInfo();
+ if (ii)
+ {
+ QCString nm = ii->includeName;
+ if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
+ if (!nm.isEmpty())
+ {
+ int header_id=insertPath(ii->fileDef->absFilePath(),!ii->fileDef->isReference());
+ DBG_CTX(("-----> ClassDef includeInfo for %s\n", nm.data()));
+ DBG_CTX((" local : %d\n", ii->local));
+ DBG_CTX((" imported : %d\n", ii->imported));
+ DBG_CTX((" indirect : %d\n", ii->indirect));
+ DBG_CTX(("header: %s\n", ii->fileDef->absFilePath().data()));
+ DBG_CTX((" file_id : %d\n", file_id));
+ DBG_CTX((" header_id: %d\n", header_id));
+
+ if(header_id!=-1)
+ {
+ bindIntParameter(compounddef_insert,":header_id",header_id);
+ }
+ }
+ }
+
+ getSQLDesc(compounddef_insert,":briefdescription",cd->briefDescription(),cd);
+ getSQLDesc(compounddef_insert,":detaileddescription",cd->documentation(),cd);
+
step(compounddef_insert);
// + list of direct super classes
if (cd->baseClasses())
{
BaseClassListIterator bcli(*cd->baseClasses());
- BaseClassDef *bcd;
+ const BaseClassDef *bcd;
for (bcli.toFirst();(bcd=bcli.current());++bcli)
{
- int refid = insertRefid(bcd->classDef->getOutputFileBase());
- bindIntParameter(basecompoundref_insert,":refid", refid);
- bindIntParameter(basecompoundref_insert,":prot",bcd->prot);
- bindIntParameter(basecompoundref_insert,":virt",bcd->virt);
-
- if (!bcd->templSpecifiers.isEmpty())
- {
- bindTextParameter(basecompoundref_insert,":base",insertTemplateSpecifierInScope(bcd->classDef->name(),bcd->templSpecifiers),FALSE);
- }
- else
- {
- bindTextParameter(basecompoundref_insert,":base",bcd->classDef->displayName(),FALSE);
- }
- bindTextParameter(basecompoundref_insert,":derived",cd->displayName(),FALSE);
- step(basecompoundref_insert);
+ struct Refid base_refid = insertRefid(bcd->classDef->getOutputFileBase());
+ struct Refid derived_refid = insertRefid(cd->getOutputFileBase());
+ bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid);
+ bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid);
+ bindIntParameter(compoundref_insert,":prot",bcd->prot);
+ bindIntParameter(compoundref_insert,":virt",bcd->virt);
+ step(compoundref_insert);
}
}
@@ -1228,54 +2051,23 @@ static void generateSqlite3ForClass(const ClassDef *cd)
if (cd->subClasses())
{
BaseClassListIterator bcli(*cd->subClasses());
- BaseClassDef *bcd;
+ const BaseClassDef *bcd;
for (bcli.toFirst();(bcd=bcli.current());++bcli)
{
- bindTextParameter(derivedcompoundref_insert,":base",cd->displayName(),FALSE);
- if (!bcd->templSpecifiers.isEmpty())
- {
- bindTextParameter(derivedcompoundref_insert,":derived",insertTemplateSpecifierInScope(bcd->classDef->name(),bcd->templSpecifiers),FALSE);
- }
- else
- {
- bindTextParameter(derivedcompoundref_insert,":derived",bcd->classDef->displayName(),FALSE);
- }
- int refid = insertRefid(bcd->classDef->getOutputFileBase());
- bindIntParameter(derivedcompoundref_insert,":refid", refid);
- bindIntParameter(derivedcompoundref_insert,":prot",bcd->prot);
- bindIntParameter(derivedcompoundref_insert,":virt",bcd->virt);
- step(derivedcompoundref_insert);
+ struct Refid derived_refid = insertRefid(bcd->classDef->getOutputFileBase());
+ struct Refid base_refid = insertRefid(cd->getOutputFileBase());
+ bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid);
+ bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid);
+ bindIntParameter(compoundref_insert,":prot",bcd->prot);
+ bindIntParameter(compoundref_insert,":virt",bcd->virt);
+ step(compoundref_insert);
}
}
- // + include file
- IncludeInfo *ii=cd->includeInfo();
- if (ii)
- {
- QCString nm = ii->includeName;
- if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
- if (!nm.isEmpty())
- {
- int id_dst=insertFile(nm);
- if (id_dst!=-1) {
- bindIntParameter(incl_select,":local",ii->local);
- bindIntParameter(incl_select,":id_src",id_file);
- bindIntParameter(incl_select,":id_dst",id_dst);
- int count=step(incl_select,TRUE,TRUE);
- if (count==0)
- {
- bindIntParameter(incl_insert,":local",ii->local);
- bindIntParameter(incl_insert,":id_src",id_file);
- bindIntParameter(incl_insert,":id_dst",id_dst);
- step(incl_insert);
- }
- }
- }
- }
// + list of inner classes
- writeInnerClasses(cd->getClassSDict());
+ writeInnerClasses(cd->getClassSDict(),refid);
- // - template argument list(s)
+ // + template argument list(s)
writeTemplateList(cd);
// + member groups
@@ -1285,41 +2077,62 @@ static void generateSqlite3ForClass(const ClassDef *cd)
MemberGroup *mg;
for (;(mg=mgli.current());++mgli)
{
- generateSqlite3Section(cd,mg->members(),"user-defined",mg->header(),
+ generateSqlite3Section(cd,mg->members(),refid,"user-defined",mg->header(),
mg->documentation());
}
}
- // + list of all members
+ // this is just a list of *local* members
QListIterator<MemberList> mli(cd->getMemberLists());
MemberList *ml;
for (mli.toFirst();(ml=mli.current());++mli)
{
if ((ml->listType()&MemberListType_detailedLists)==0)
{
- generateSqlite3Section(cd,ml,"user-defined");//g_xmlSectionMapper.find(ml->listType()));
+ generateSqlite3Section(cd,ml,refid,"user-defined");
}
}
+
+ // + list of all members
+ associateAllClassMembers(cd, refid);
}
+// kinds: constants library module namespace package
static void generateSqlite3ForNamespace(const NamespaceDef *nd)
{
// + contained class definitions
// + contained namespace definitions
// + member groups
// + normal members
- // - brief desc
- // - detailed desc
- // - location
+ // + brief desc
+ // + detailed desc
+ // + location (file_id, line, column)
// - files containing (parts of) the namespace definition
if (nd->isReference() || nd->isHidden()) return; // skip external references
+ struct Refid refid = insertRefid(nd->getOutputFileBase());
+ if(!refid.created && compounddefExists(refid)){return;}
+ bindIntParameter(compounddef_insert,":rowid", refid.rowid);
+
+ bindTextParameter(compounddef_insert,":name",nd->name());
+ bindTextParameter(compounddef_insert,":title",nd->title(), FALSE);
+ bindTextParameter(compounddef_insert,":kind","namespace",FALSE);
+
+ int file_id = insertPath(nd->getDefFileName());
+ bindIntParameter(compounddef_insert,":file_id",file_id);
+ bindIntParameter(compounddef_insert,":line",nd->getDefLine());
+ bindIntParameter(compounddef_insert,":column",nd->getDefColumn());
+
+ getSQLDesc(compounddef_insert,":briefdescription",nd->briefDescription(),nd);
+ getSQLDesc(compounddef_insert,":detaileddescription",nd->documentation(),nd);
+
+ step(compounddef_insert);
// + contained class definitions
- writeInnerClasses(nd->getClassSDict());
+ writeInnerClasses(nd->getClassSDict(),refid);
// + contained namespace definitions
- writeInnerNamespaces(nd->getNamespaceSDict());
+ writeInnerNamespaces(nd->getNamespaceSDict(),refid);
// + member groups
if (nd->getMemberGroupSDict())
@@ -1328,7 +2141,7 @@ static void generateSqlite3ForNamespace(const NamespaceDef *nd)
MemberGroup *mg;
for (;(mg=mgli.current());++mgli)
{
- generateSqlite3Section(nd,mg->members(),"user-defined",mg->header(),
+ generateSqlite3Section(nd,mg->members(),refid,"user-defined",mg->header(),
mg->documentation());
}
}
@@ -1340,29 +2153,48 @@ static void generateSqlite3ForNamespace(const NamespaceDef *nd)
{
if ((ml->listType()&MemberListType_declarationLists)!=0)
{
- generateSqlite3Section(nd,ml,"user-defined");//g_xmlSectionMapper.find(ml->listType()));
+ generateSqlite3Section(nd,ml,refid,"user-defined");
}
}
}
+// kind: file
static void generateSqlite3ForFile(const FileDef *fd)
{
// + includes files
// + includedby files
- // - include graph
- // - included by graph
+ // x include graph
+ // x included by graph
// + contained class definitions
// + contained namespace definitions
// + member groups
// + normal members
- // - brief desc
- // - detailed desc
- // - source code
- // - location
+ // + brief desc
+ // + detailed desc
+ // x source code
+ // + location (file_id, line, column)
// - number of lines
if (fd->isReference()) return; // skip external references
+ struct Refid refid = insertRefid(fd->getOutputFileBase());
+ if(!refid.created && compounddefExists(refid)){return;}
+ bindIntParameter(compounddef_insert,":rowid", refid.rowid);
+
+ bindTextParameter(compounddef_insert,":name",fd->name(),FALSE);
+ bindTextParameter(compounddef_insert,":title",fd->title(),FALSE);
+ bindTextParameter(compounddef_insert,":kind","file",FALSE);
+
+ int file_id = insertPath(fd->getDefFileName());
+ bindIntParameter(compounddef_insert,":file_id",file_id);
+ bindIntParameter(compounddef_insert,":line",fd->getDefLine());
+ bindIntParameter(compounddef_insert,":column",fd->getDefColumn());
+
+ getSQLDesc(compounddef_insert,":briefdescription",fd->briefDescription(),fd);
+ getSQLDesc(compounddef_insert,":detaileddescription",fd->documentation(),fd);
+
+ step(compounddef_insert);
+
// + includes files
IncludeInfo *ii;
if (fd->includeFileList())
@@ -1370,15 +2202,48 @@ static void generateSqlite3ForFile(const FileDef *fd)
QListIterator<IncludeInfo> ili(*fd->includeFileList());
for (ili.toFirst();(ii=ili.current());++ili)
{
- int id_src=insertFile(fd->absFilePath().data());
- int id_dst=insertFile(ii->includeName.data());
+ int src_id=insertPath(fd->absFilePath(),!fd->isReference());
+ int dst_id;
+ QCString dst_path;
+
+ if(ii->fileDef) // found file
+ {
+ if(ii->fileDef->isReference())
+ {
+ // strip tagfile from path
+ QCString tagfile = ii->fileDef->getReference();
+ dst_path = ii->fileDef->absFilePath().copy();
+ dst_path.stripPrefix(tagfile+":");
+ }
+ else
+ {
+ dst_path = ii->fileDef->absFilePath();
+ }
+ dst_id = insertPath(dst_path,ii->local);
+ }
+ else // can't find file
+ {
+ dst_id = insertPath(ii->includeName,ii->local,FALSE);
+ }
+
+ DBG_CTX(("-----> FileDef includeInfo for %s\n", ii->includeName.data()));
+ DBG_CTX((" local: %d\n", ii->local));
+ DBG_CTX((" imported: %d\n", ii->imported));
+ DBG_CTX((" indirect: %d\n", ii->indirect));
+ if(ii->fileDef)
+ {
+ DBG_CTX(("include: %s\n", ii->fileDef->absFilePath().data()));
+ }
+ DBG_CTX((" src_id : %d\n", src_id));
+ DBG_CTX((" dst_id: %d\n", dst_id));
+
bindIntParameter(incl_select,":local",ii->local);
- bindIntParameter(incl_select,":id_src",id_src);
- bindIntParameter(incl_select,":id_dst",id_dst);
+ bindIntParameter(incl_select,":src_id",src_id);
+ bindIntParameter(incl_select,":dst_id",dst_id);
if (step(incl_select,TRUE,TRUE)==0) {
bindIntParameter(incl_insert,":local",ii->local);
- bindIntParameter(incl_insert,":id_src",id_src);
- bindIntParameter(incl_insert,":id_dst",id_dst);
+ bindIntParameter(incl_insert,":src_id",src_id);
+ bindIntParameter(incl_insert,":dst_id",dst_id);
step(incl_insert);
}
}
@@ -1390,15 +2255,37 @@ static void generateSqlite3ForFile(const FileDef *fd)
QListIterator<IncludeInfo> ili(*fd->includedByFileList());
for (ili.toFirst();(ii=ili.current());++ili)
{
- int id_src=insertFile(ii->includeName);
- int id_dst=insertFile(fd->absFilePath());
+ int dst_id=insertPath(fd->absFilePath(),!fd->isReference());
+ int src_id;
+ QCString src_path;
+
+ if(ii->fileDef) // found file
+ {
+ if(ii->fileDef->isReference())
+ {
+ // strip tagfile from path
+ QCString tagfile = ii->fileDef->getReference();
+ src_path = ii->fileDef->absFilePath().copy();
+ src_path.stripPrefix(tagfile+":");
+ }
+ else
+ {
+ src_path = ii->fileDef->absFilePath();
+ }
+ src_id = insertPath(src_path,ii->local);
+ }
+ else // can't find file
+ {
+ src_id = insertPath(ii->includeName,ii->local,FALSE);
+ }
+
bindIntParameter(incl_select,":local",ii->local);
- bindIntParameter(incl_select,":id_src",id_src);
- bindIntParameter(incl_select,":id_dst",id_dst);
+ bindIntParameter(incl_select,":src_id",src_id);
+ bindIntParameter(incl_select,":dst_id",dst_id);
if (step(incl_select,TRUE,TRUE)==0) {
bindIntParameter(incl_insert,":local",ii->local);
- bindIntParameter(incl_insert,":id_src",id_src);
- bindIntParameter(incl_insert,":id_dst",id_dst);
+ bindIntParameter(incl_insert,":src_id",src_id);
+ bindIntParameter(incl_insert,":dst_id",dst_id);
step(incl_insert);
}
}
@@ -1407,13 +2294,13 @@ static void generateSqlite3ForFile(const FileDef *fd)
// + contained class definitions
if (fd->getClassSDict())
{
- writeInnerClasses(fd->getClassSDict());
+ writeInnerClasses(fd->getClassSDict(),refid);
}
// + contained namespace definitions
if (fd->getNamespaceSDict())
{
- writeInnerNamespaces(fd->getNamespaceSDict());
+ writeInnerNamespaces(fd->getNamespaceSDict(),refid);
}
// + member groups
@@ -1423,7 +2310,7 @@ static void generateSqlite3ForFile(const FileDef *fd)
MemberGroup *mg;
for (;(mg=mgli.current());++mgli)
{
- generateSqlite3Section(fd,mg->members(),"user-defined",mg->header(),
+ generateSqlite3Section(fd,mg->members(),refid,"user-defined",mg->header(),
mg->documentation());
}
}
@@ -1435,24 +2322,201 @@ static void generateSqlite3ForFile(const FileDef *fd)
{
if ((ml->listType()&MemberListType_declarationLists)!=0)
{
- generateSqlite3Section(fd,ml,"user-defined");//g_xmlSectionMapper.find(ml->listType()));
+ generateSqlite3Section(fd,ml,refid,"user-defined");
}
}
}
+// kind: group
static void generateSqlite3ForGroup(const GroupDef *gd)
{
-#warning WorkInProgress
+ // + members
+ // + member groups
+ // + files
+ // + classes
+ // + namespaces
+ // - packages
+ // + pages
+ // + child groups
+ // - examples
+ // + brief description
+ // + detailed description
+
+ if (gd->isReference()) return; // skip external references.
+
+ struct Refid refid = insertRefid(gd->getOutputFileBase());
+ if(!refid.created && compounddefExists(refid)){return;}
+ bindIntParameter(compounddef_insert,":rowid", refid.rowid);
+
+ bindTextParameter(compounddef_insert,":name",gd->name());
+ bindTextParameter(compounddef_insert,":title",gd->groupTitle(), FALSE);
+ bindTextParameter(compounddef_insert,":kind","group",FALSE);
+
+ int file_id = insertPath(gd->getDefFileName());
+ bindIntParameter(compounddef_insert,":file_id",file_id);
+ bindIntParameter(compounddef_insert,":line",gd->getDefLine());
+ bindIntParameter(compounddef_insert,":column",gd->getDefColumn());
+
+ getSQLDesc(compounddef_insert,":briefdescription",gd->briefDescription(),gd);
+ getSQLDesc(compounddef_insert,":detaileddescription",gd->documentation(),gd);
+
+ step(compounddef_insert);
+
+ // + files
+ writeInnerFiles(gd->getFiles(),refid);
+
+ // + classes
+ writeInnerClasses(gd->getClasses(),refid);
+
+ // + namespaces
+ writeInnerNamespaces(gd->getNamespaces(),refid);
+
+ // + pages
+ writeInnerPages(gd->getPages(),refid);
+
+ // + groups
+ writeInnerGroups(gd->getSubGroups(),refid);
+
+ // + member groups
+ if (gd->getMemberGroupSDict())
+ {
+ MemberGroupSDict::Iterator mgli(*gd->getMemberGroupSDict());
+ MemberGroup *mg;
+ for (;(mg=mgli.current());++mgli)
+ {
+ generateSqlite3Section(gd,mg->members(),refid,"user-defined",mg->header(),
+ mg->documentation());
+ }
+ }
+
+ // + members
+ QListIterator<MemberList> mli(gd->getMemberLists());
+ MemberList *ml;
+ for (mli.toFirst();(ml=mli.current());++mli)
+ {
+ if ((ml->listType()&MemberListType_declarationLists)!=0)
+ {
+ generateSqlite3Section(gd,ml,refid,"user-defined");
+ }
+ }
}
+// kind: dir
static void generateSqlite3ForDir(const DirDef *dd)
{
-#warning WorkInProgress
+ // + dirs
+ // + files
+ // + briefdescription
+ // + detaileddescription
+ // + location (below uses file_id, line, column; XML just uses file)
+ if (dd->isReference()) return; // skip external references
+
+ struct Refid refid = insertRefid(dd->getOutputFileBase());
+ if(!refid.created && compounddefExists(refid)){return;}
+ bindIntParameter(compounddef_insert,":rowid", refid.rowid);
+
+ bindTextParameter(compounddef_insert,":name",dd->displayName());
+ bindTextParameter(compounddef_insert,":kind","dir",FALSE);
+
+ int file_id = insertPath(dd->getDefFileName(),TRUE,TRUE,2);
+ bindIntParameter(compounddef_insert,":file_id",file_id);
+
+ /*
+ line and column are weird here, but:
+ - dir goes into compounddef with all of the others
+ - the semantics would be fine if we set them to NULL here
+ - but defining line and column as NOT NULL is an important promise
+ for other compounds, so I don't want to loosen it
+
+ For reference, the queries return 1.
+ 0 or -1 make more sense, but I see that as a change for DirDef.
+ */
+ bindIntParameter(compounddef_insert,":line",dd->getDefLine());
+ bindIntParameter(compounddef_insert,":column",dd->getDefColumn());
+
+ getSQLDesc(compounddef_insert,":briefdescription",dd->briefDescription(),dd);
+ getSQLDesc(compounddef_insert,":detaileddescription",dd->documentation(),dd);
+
+ step(compounddef_insert);
+
+ // + files
+ writeInnerDirs(&dd->subDirs(),refid);
+
+ // + files
+ writeInnerFiles(dd->getFiles(),refid);
}
+// kinds: page, example
static void generateSqlite3ForPage(const PageDef *pd,bool isExample)
{
-#warning WorkInProgress
+ // + name
+ // + title
+ // + brief description
+ // + documentation (detailed description)
+ // + inbody documentation
+ // + sub pages
+ if (pd->isReference()) return; // skip external references.
+
+ // TODO: do we more special handling if isExample?
+
+ QCString qrefid = pd->getOutputFileBase();
+ if (pd->getGroupDef())
+ {
+ qrefid+=(QCString)"_"+pd->name();
+ }
+ if (qrefid=="index") qrefid="indexpage"; // to prevent overwriting the generated index page.
+
+ struct Refid refid = insertRefid(qrefid);
+
+ // can omit a page that already has a refid
+ if(!refid.created && compounddefExists(refid)){return;}
+
+ bindIntParameter(compounddef_insert,":rowid",refid.rowid);
+ // + name
+ bindTextParameter(compounddef_insert,":name",pd->name());
+
+ QCString title;
+ if (pd==Doxygen::mainPage) // main page is special
+ {
+ if (!pd->title().isEmpty() && pd->title().lower()!="notitle")
+ {
+ title = filterTitle(convertCharEntitiesToUTF8(Doxygen::mainPage->title()));
+ }
+ else
+ {
+ title = Config_getString(PROJECT_NAME);
+ }
+ }
+ else
+ {
+ SectionInfo *si = Doxygen::sectionDict->find(pd->name());
+ if (si)
+ {
+ title = si->title;
+ }
+
+ if(!title){title = pd->title();}
+ }
+
+ // + title
+ bindTextParameter(compounddef_insert,":title",title,FALSE);
+
+ bindTextParameter(compounddef_insert,":kind", isExample ? "example" : "page");
+
+ int file_id = insertPath(pd->getDefFileName());
+
+ bindIntParameter(compounddef_insert,":file_id",file_id);
+ bindIntParameter(compounddef_insert,":line",pd->getDefLine());
+ bindIntParameter(compounddef_insert,":column",pd->getDefColumn());
+
+ // + brief description
+ getSQLDesc(compounddef_insert,":briefdescription",pd->briefDescription(),pd);
+ // + documentation (detailed description)
+ getSQLDesc(compounddef_insert,":detaileddescription",pd->documentation(),pd);
+
+ step(compounddef_insert);
+ // + sub pages
+ writeInnerPages(pd->getSubPages(),refid);
}
@@ -1463,6 +2527,7 @@ static sqlite3* openDbConnection()
QDir sqlite3Dir(outputDirectory);
sqlite3 *db;
int rc;
+ struct stat buf;
rc = sqlite3_initialize();
if (rc != SQLITE_OK)
@@ -1470,7 +2535,21 @@ static sqlite3* openDbConnection()
msg("sqlite3_initialize failed\n");
return NULL;
}
- rc = sqlite3_open_v2(outputDirectory+"/doxygen_sqlite3.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
+
+
+ if (stat (outputDirectory+"/doxygen_sqlite3.db", &buf) == 0)
+ {
+ msg("doxygen_sqlite3.db already exists! aborting sqlite3 output generation!\n");
+ msg("If you wish to re-generate the database, remove or archive the existing copy first.\n");
+ return NULL;
+ }
+
+ rc = sqlite3_open_v2(
+ outputDirectory+"/doxygen_sqlite3.db",
+ &db,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+ 0
+ );
if (rc != SQLITE_OK)
{
sqlite3_close(db);
@@ -1497,10 +2576,16 @@ void generateSqlite3()
{
return;
}
+
+# ifdef SQLITE3_DEBUG
+ // debug: show all executed statements
+ sqlite3_trace(db, &sqlLog, NULL);
+# endif
+
beginTransaction(db);
pragmaTuning(db);
- if (-1==initializeSchema(db))
+ if (-1==initializeTables(db))
return;
if ( -1 == prepareStatements(db) )
@@ -1509,9 +2594,11 @@ void generateSqlite3()
return;
}
+ recordMetadata();
+
// + classes
ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd;
+ const ClassDef *cd;
for (cli.toFirst();(cd=cli.current());++cli)
{
msg("Generating Sqlite3 output for class %s\n",cd->name().data());
@@ -1520,7 +2607,7 @@ void generateSqlite3()
// + namespaces
NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (nli.toFirst();(nd=nli.current());++nli)
{
msg("Generating Sqlite3 output for namespace %s\n",nd->name().data());
@@ -1533,7 +2620,7 @@ void generateSqlite3()
for (;(fn=fnli.current());++fnli)
{
FileNameIterator fni(*fn);
- FileDef *fd;
+ const FileDef *fd;
for (;(fd=fni.current());++fni)
{
msg("Generating Sqlite3 output for file %s\n",fd->name().data());
@@ -1543,7 +2630,7 @@ void generateSqlite3()
// + groups
GroupSDict::Iterator gli(*Doxygen::groupSDict);
- GroupDef *gd;
+ const GroupDef *gd;
for (;(gd=gli.current());++gli)
{
msg("Generating Sqlite3 output for group %s\n",gd->name().data());
@@ -1553,7 +2640,7 @@ void generateSqlite3()
// + page
{
PageSDict::Iterator pdi(*Doxygen::pageSDict);
- PageDef *pd=0;
+ const PageDef *pd=0;
for (pdi.toFirst();(pd=pdi.current());++pdi)
{
msg("Generating Sqlite3 output for page %s\n",pd->name().data());
@@ -1563,7 +2650,7 @@ void generateSqlite3()
// + dirs
{
- DirDef *dir;
+ const DirDef *dir;
DirSDict::Iterator sdi(*Doxygen::directories);
for (sdi.toFirst();(dir=sdi.current());++sdi)
{
@@ -1575,7 +2662,7 @@ void generateSqlite3()
// + examples
{
PageSDict::Iterator pdi(*Doxygen::exampleSDict);
- PageDef *pd=0;
+ const PageDef *pd=0;
for (pdi.toFirst();(pd=pdi.current());++pdi)
{
msg("Generating Sqlite3 output for example %s\n",pd->name().data());
@@ -1590,6 +2677,11 @@ void generateSqlite3()
generateSqlite3ForPage(Doxygen::mainPage,FALSE);
}
+ // TODO: copied from initializeSchema; not certain if we should say/do more
+ // if there's a failure here?
+ if (-1==initializeViews(db))
+ return;
+
endTransaction(db);
}
diff --git a/src/tagreader.cpp b/src/tagreader.cpp
index 82e4712..1afa30d 100644
--- a/src/tagreader.cpp
+++ b/src/tagreader.cpp
@@ -18,6 +18,7 @@
#include "tagreader.h"
+#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
@@ -101,6 +102,7 @@ class TagClassInfo
QCString name;
QCString filename;
QCString clangId;
+ QCString anchor;
TagAnchorInfoList docAnchors;
QList<BaseInfo> *bases;
QList<TagMemberInfo> members;
@@ -381,7 +383,7 @@ class TagFileParser : public QXmlDefaultHandler
}
else
{
- warn("Unknown compound attribute `%s' found!\n",kind.data());
+ warn("Unknown compound attribute `%s' found!",kind.data());
m_state = Invalid;
}
if (isObjC=="yes" && m_curClass)
@@ -409,7 +411,7 @@ class TagFileParser : public QXmlDefaultHandler
case InPackage: m_tagFilePackages.append(m_curPackage);
m_curPackage=0; break;
default:
- warn("tag `compound' was not expected!\n");
+ warn("tag `compound' was not expected!");
}
}
@@ -455,7 +457,7 @@ class TagFileParser : public QXmlDefaultHandler
case InNamespace: m_curNamespace->members.append(m_curMember); break;
case InGroup: m_curGroup->members.append(m_curMember); break;
case InPackage: m_curPackage->members.append(m_curMember); break;
- default: warn("Unexpected tag `member' found\n"); break;
+ default: warn("Unexpected tag `member' found"); break;
}
}
@@ -473,7 +475,7 @@ class TagFileParser : public QXmlDefaultHandler
}
else
{
- warn("Found enumvalue tag outside of member tag\n");
+ warn("Found `enumvalue' tag outside of member tag");
}
}
@@ -501,7 +503,7 @@ class TagFileParser : public QXmlDefaultHandler
case InMember: m_curMember->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
case InPackage: m_curPackage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
case InDir: m_curDir->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
- default: warn("Unexpected tag `member' found\n"); break;
+ default: warn("Unexpected tag `docanchor' found"); break;
}
}
@@ -514,7 +516,7 @@ class TagFileParser : public QXmlDefaultHandler
case InNamespace: m_curNamespace->classList.append(m_curString); break;
case InGroup: m_curGroup->classList.append(m_curString); break;
case InPackage: m_curPackage->classList.append(m_curString); break;
- default: warn("Unexpected tag `class' found\n"); break;
+ default: warn("Unexpected tag `class' found"); break;
}
}
@@ -525,7 +527,7 @@ class TagFileParser : public QXmlDefaultHandler
case InNamespace: m_curNamespace->classList.append(m_curString); break;
case InFile: m_curFile->namespaceList.append(m_curString); break;
case InGroup: m_curGroup->namespaceList.append(m_curString); break;
- default: warn("Unexpected tag `namespace' found\n"); break;
+ default: warn("Unexpected tag `namespace' found"); break;
}
}
@@ -535,7 +537,7 @@ class TagFileParser : public QXmlDefaultHandler
{
case InGroup: m_curGroup->fileList.append(m_curString); break;
case InDir: m_curDir->fileList.append(m_curString); break;
- default: warn("Unexpected tag `file' found\n"); break;
+ default: warn("Unexpected tag `file' found"); break;
}
}
@@ -544,7 +546,7 @@ class TagFileParser : public QXmlDefaultHandler
switch(m_state)
{
case InGroup: m_curGroup->fileList.append(m_curString); break;
- default: warn("Unexpected tag `page' found\n"); break;
+ default: warn("Unexpected tag `page' found"); break;
}
}
@@ -553,7 +555,7 @@ class TagFileParser : public QXmlDefaultHandler
switch(m_state)
{
case InDir: m_curDir->subdirList.append(m_curString); break;
- default: warn("Unexpected tag `page' found\n"); break;
+ default: warn("Unexpected tag `dir' found"); break;
}
}
@@ -577,7 +579,7 @@ class TagFileParser : public QXmlDefaultHandler
}
else
{
- warn("Unexpected tag `type' found\n");
+ warn("Unexpected tag `type' found");
}
}
@@ -593,7 +595,7 @@ class TagFileParser : public QXmlDefaultHandler
case InDir: m_curDir->name = m_curString; break;
case InMember: m_curMember->name = m_curString; break;
case InPackage: m_curPackage->name = m_curString; break;
- default: warn("Unexpected tag `name' found\n"); break;
+ default: warn("Unexpected tag `name' found"); break;
}
}
@@ -627,7 +629,7 @@ class TagFileParser : public QXmlDefaultHandler
}
else
{
- warn("Unexpected tag `base' found\n");
+ warn("Unexpected tag `base' found");
}
}
@@ -639,7 +641,7 @@ class TagFileParser : public QXmlDefaultHandler
}
else
{
- warn("Unexpected tag `base' found\n");
+ warn("Unexpected tag `base' found");
}
}
@@ -656,7 +658,7 @@ class TagFileParser : public QXmlDefaultHandler
}
else
{
- warn("Unexpected tag `includes' found\n");
+ warn("Unexpected tag `includes' found");
}
m_curString="";
}
@@ -679,7 +681,7 @@ class TagFileParser : public QXmlDefaultHandler
}
else
{
- warn("Unexpected tag `templarg' found\n");
+ warn("Unexpected tag `templarg' found");
}
}
@@ -694,7 +696,7 @@ class TagFileParser : public QXmlDefaultHandler
case InPage: m_curPage->filename = m_curString; break;
case InPackage: m_curPackage->filename = m_curString; break;
case InDir: m_curDir->filename = m_curString; break;
- default: warn("Unexpected tag `filename' found\n"); break;
+ default: warn("Unexpected tag `filename' found"); break;
}
}
@@ -704,7 +706,7 @@ class TagFileParser : public QXmlDefaultHandler
{
case InFile: m_curFile->path = m_curString; break;
case InDir: m_curDir->path = m_curString; break;
- default: warn("Unexpected tag `path' found\n"); break;
+ default: warn("Unexpected tag `path' found"); break;
}
}
@@ -714,9 +716,13 @@ class TagFileParser : public QXmlDefaultHandler
{
m_curMember->anchor = m_curString;
}
+ else if (m_state==InClass)
+ {
+ m_curClass->anchor = m_curString;
+ }
else
{
- warn("Unexpected tag `anchor' found\n");
+ warn("Unexpected tag `anchor' found");
}
}
@@ -736,7 +742,7 @@ class TagFileParser : public QXmlDefaultHandler
}
else
{
- warn("warning: Unexpected tag `anchor' found\n");
+ warn("Unexpected tag `clangid' found");
}
}
@@ -750,7 +756,7 @@ class TagFileParser : public QXmlDefaultHandler
}
else
{
- warn("Unexpected tag `anchorfile' found\n");
+ warn("Unexpected tag `anchorfile' found");
}
}
@@ -762,7 +768,7 @@ class TagFileParser : public QXmlDefaultHandler
}
else
{
- warn("Unexpected tag `arglist' found\n");
+ warn("Unexpected tag `arglist' found");
}
}
void endTitle()
@@ -771,7 +777,7 @@ class TagFileParser : public QXmlDefaultHandler
{
case InGroup: m_curGroup->title = m_curString; break;
case InPage: m_curPage->title = m_curString; break;
- default: warn("Unexpected tag `title' found\n"); break;
+ default: warn("Unexpected tag `title' found"); break;
}
}
@@ -783,7 +789,7 @@ class TagFileParser : public QXmlDefaultHandler
}
else
{
- warn("Unexpected tag `subgroup' found\n");
+ warn("Unexpected tag `subgroup' found");
}
}
@@ -878,7 +884,7 @@ class TagFileParser : public QXmlDefaultHandler
}
else
{
- warn("Unknown tag `%s' found!\n",name.data());
+ warn("Unknown tag `%s' found!",name.data());
}
return TRUE;
}
@@ -893,7 +899,7 @@ class TagFileParser : public QXmlDefaultHandler
}
else
{
- warn("Unknown tag `%s' found!\n",name.data());
+ warn("Unknown tag `%s' found!",name.data());
}
return TRUE;
}
@@ -1157,7 +1163,7 @@ void TagFileParser::addDocAnchors(Entry *e,const TagAnchorInfoList &l)
}
else
{
- warn("Duplicate anchor %s found\n",ta->label.data());
+ warn("Duplicate anchor %s found",ta->label.data());
}
}
}
@@ -1322,6 +1328,9 @@ void TagFileParser::buildLists(Entry *root)
case TagClassInfo::Category: ce->spec = Entry::Category; break;
case TagClassInfo::Service: ce->spec = Entry::Service; break;
case TagClassInfo::Singleton: ce->spec = Entry::Singleton; break;
+ case TagClassInfo::None: // should never happen, means not properly initialized
+ assert(tci->kind != TagClassInfo::None);
+ break;
}
ce->name = tci->name;
if (tci->kind==TagClassInfo::Protocol)
@@ -1331,6 +1340,7 @@ void TagFileParser::buildLists(Entry *root)
addDocAnchors(ce,tci->docAnchors);
TagInfo *ti = new TagInfo;
ti->tagName = m_tagName;
+ ti->anchor = tci->anchor;
ti->fileName = tci->filename;
ce->id = tci->clangId;
ce->tagInfo = ti;
diff --git a/src/template.cpp b/src/template.cpp
index 3e39d3c..b1435ce 100644
--- a/src/template.cpp
+++ b/src/template.cpp
@@ -698,7 +698,7 @@ class FilterTexLabel
{
if (v.isValid() && (v.type()==TemplateVariant::String))
{
- return TemplateVariant(latexEscapeLabelName(v.toString(),FALSE),TRUE);
+ return TemplateVariant(latexEscapeLabelName(v.toString()),TRUE);
}
else
{
@@ -717,7 +717,7 @@ class FilterTexIndex
{
if (v.isValid() && (v.type()==TemplateVariant::String))
{
- return TemplateVariant(latexEscapeIndexChars(v.toString(),FALSE),TRUE);
+ return TemplateVariant(latexEscapeIndexChars(v.toString()),TRUE);
}
else
{
diff --git a/src/textdocvisitor.cpp b/src/textdocvisitor.cpp
index c899232..691e426 100644
--- a/src/textdocvisitor.cpp
+++ b/src/textdocvisitor.cpp
@@ -21,6 +21,7 @@
#include "message.h"
#include "util.h"
#include "htmlentity.h"
+#include "emoji.h"
//-------------------------------------------------------------------------
@@ -37,6 +38,18 @@ void TextDocVisitor::visit(DocSymbol *s)
}
}
+void TextDocVisitor::visit(DocEmoji *s)
+{
+ const char *res = EmojiEntityMapper::instance()->html(s->emoji());
+ if (res)
+ {
+ filter(res);
+ }
+ else
+ {
+ err("text: non supported Emoji-entity found: %s\n",EmojiEntityMapper::instance()->html(s->emoji()));
+ }
+}
void TextDocVisitor::filter(const char *str)
{
diff --git a/src/textdocvisitor.h b/src/textdocvisitor.h
index 1bbc357..bbc70e8 100644
--- a/src/textdocvisitor.h
+++ b/src/textdocvisitor.h
@@ -40,6 +40,7 @@ class TextDocVisitor : public DocVisitor
void visit(DocLinkedWord *w) { filter(w->word()); }
void visit(DocWhiteSpace *) { m_t << " "; }
void visit(DocSymbol *);
+ void visit(DocEmoji *);
void visit(DocURL *u) { filter(u->url()); }
void visit(DocLineBreak *) { m_t << " "; }
void visit(DocHorRuler *) {}
diff --git a/src/translator.h b/src/translator.h
index 9da2317..ac55911 100644
--- a/src/translator.h
+++ b/src/translator.h
@@ -46,7 +46,7 @@ class Translator
/*!
* Sets the LaTeX font encoding to be used. The default is set to `T1`,
* in case another font encoding has to be used this can be specified with
- * this routine. In case no font encoding is required the empty string
+ * this routine. In case no font encoding is required the empty string
* can be returned.
*/
virtual QCString latexFontenc() { return "T1"; }
@@ -616,6 +616,36 @@ class Translator
virtual QCString trFunctionAndProc() = 0;
virtual QCString trVhdlType(uint64 type,bool single) = 0;
virtual QCString trCustomReference(const char *name) = 0;
+
+ virtual QCString trConstants() = 0;
+ virtual QCString trConstantDocumentation() = 0;
+ virtual QCString trSequences() = 0;
+ virtual QCString trSequenceDocumentation() = 0;
+ virtual QCString trDictionaries() = 0;
+ virtual QCString trDictionaryDocumentation() = 0;
+ virtual QCString trSliceInterfaces() = 0;
+ virtual QCString trInterfaceIndex() = 0;
+ virtual QCString trInterfaceList() = 0;
+ virtual QCString trInterfaceListDescription() = 0;
+ virtual QCString trInterfaceHierarchy() = 0;
+ virtual QCString trInterfaceHierarchyDescription() = 0;
+ virtual QCString trInterfaceDocumentation() = 0;
+ virtual QCString trStructs() = 0;
+ virtual QCString trStructIndex() = 0;
+ virtual QCString trStructList() = 0;
+ virtual QCString trStructListDescription() = 0;
+ virtual QCString trStructDocumentation() = 0;
+ virtual QCString trExceptionIndex() = 0;
+ virtual QCString trExceptionList() = 0;
+ virtual QCString trExceptionListDescription() = 0;
+ virtual QCString trExceptionHierarchy() = 0;
+ virtual QCString trExceptionHierarchyDescription() = 0;
+ virtual QCString trExceptionDocumentation() = 0;
+ virtual QCString trCompoundReferenceSlice(const char *clName, ClassDef::CompoundType compType, bool isLocal) = 0;
+ virtual QCString trOperations() = 0;
+ virtual QCString trOperationDocumentation() = 0;
+ virtual QCString trDataMembers() = 0;
+ virtual QCString trDataMemberDocumentation() = 0;
};
#endif
diff --git a/src/translator_adapter.h b/src/translator_adapter.h
index e66c9bf..b0c8a24 100644
--- a/src/translator_adapter.h
+++ b/src/translator_adapter.h
@@ -70,8 +70,96 @@ class TranslatorAdapter_1_8_15 : public TranslatorAdapterBase
virtual QCString trVhdlType(uint64 type,bool single)
{ return english.trVhdlType(type,single); }
+
virtual QCString trCustomReference(const char *name)
{ return english.trCustomReference(name); }
+
+ virtual QCString trConstants()
+ { return english.trConstants(); }
+
+ virtual QCString trConstantDocumentation()
+ { return english.trConstantDocumentation(); }
+
+ virtual QCString trSequences()
+ { return english.trSequences(); }
+
+ virtual QCString trSequenceDocumentation()
+ { return english.trSequenceDocumentation(); }
+
+ virtual QCString trDictionaries()
+ { return english.trDictionaries(); }
+
+ virtual QCString trDictionaryDocumentation()
+ { return english.trDictionaryDocumentation(); }
+
+ virtual QCString trSliceInterfaces()
+ { return english.trSliceInterfaces(); }
+
+ virtual QCString trInterfaceIndex()
+ { return english.trInterfaceIndex(); }
+
+ virtual QCString trInterfaceList()
+ { return english.trInterfaceList(); }
+
+ virtual QCString trInterfaceListDescription()
+ { return english.trInterfaceListDescription(); }
+
+ virtual QCString trInterfaceHierarchy()
+ { return english.trInterfaceHierarchy(); }
+
+ virtual QCString trInterfaceHierarchyDescription()
+ { return english.trInterfaceHierarchyDescription(); }
+
+ virtual QCString trInterfaceDocumentation()
+ { return english.trInterfaceDocumentation(); }
+
+ virtual QCString trStructs()
+ { return english.trStructs(); }
+
+ virtual QCString trStructIndex()
+ { return english.trStructIndex(); }
+
+ virtual QCString trStructList()
+ { return english.trStructList(); }
+
+ virtual QCString trStructListDescription()
+ { return english.trStructListDescription(); }
+
+ virtual QCString trStructDocumentation()
+ { return english.trStructDocumentation(); }
+
+ virtual QCString trExceptionIndex()
+ { return english.trExceptionIndex(); }
+
+ virtual QCString trExceptionList()
+ { return english.trExceptionList(); }
+
+ virtual QCString trExceptionListDescription()
+ { return english.trExceptionListDescription(); }
+
+ virtual QCString trExceptionHierarchy()
+ { return english.trExceptionHierarchy(); }
+
+ virtual QCString trExceptionHierarchyDescription()
+ { return english.trExceptionHierarchyDescription(); }
+
+ virtual QCString trExceptionDocumentation()
+ { return english.trExceptionDocumentation(); }
+
+ virtual QCString trCompoundReferenceSlice(const char *clName, ClassDef::CompoundType compType, bool isLocal)
+ { return english.trCompoundReferenceSlice(clName,compType,isLocal); }
+
+ virtual QCString trOperations()
+ { return english.trOperations(); }
+
+ virtual QCString trOperationDocumentation()
+ { return english.trOperationDocumentation(); }
+
+ virtual QCString trDataMembers()
+ { return english.trDataMembers(); }
+
+ virtual QCString trDataMemberDocumentation()
+ { return english.trDataMemberDocumentation(); }
};
class TranslatorAdapter_1_8_4 : public TranslatorAdapter_1_8_15
@@ -328,4 +416,3 @@ class TranslatorAdapter_1_4_6 : public TranslatorAdapter_1_5_4
};
#endif
-
diff --git a/src/translator_br.h b/src/translator_br.h
index 774e554..c2d079a 100644
--- a/src/translator_br.h
+++ b/src/translator_br.h
@@ -14,7 +14,7 @@
* Maintainer:
* Fabio "FJTC" Jun Takada Chino <fjtc at brokenbits dot com dot br>
* Collaborators:
- * Emerson Ferreira <nuskorpios at gmail dot com>
+ * Emerson Ferreira <nuskorpios at gmail dot com>
* Thanks to Jorge Ramos, Fernando Carijo and others for their contributions.
*
* History:
@@ -47,7 +47,7 @@
#ifndef TRANSLATOR_BR_H
#define TRANSLATOR_BR_H
-class TranslatorBrazilian : public Translator
+class TranslatorBrazilian : public TranslatorAdapter_1_8_15
{
public:
@@ -610,7 +610,7 @@ class TranslatorBrazilian : public Translator
{
QCString result="Referência";
if (isTemplate) result+=" do <em>Template</em>";
- if (compType == ClassDef::Protocol)
+ if (compType == ClassDef::Protocol)
{
result+=" do ";
}
@@ -836,7 +836,7 @@ class TranslatorBrazilian : public Translator
* documentation. It should be an abbreviation of the word page.
*/
virtual QCString trPageAbbreviation()
- {
+ {
// Decidi mudar de página para "p." para ficar mais compacto.
return "p.";
}
@@ -2200,9 +2200,6 @@ class TranslatorBrazilian : public Translator
}
virtual QCString trCustomReference(const char *name)
{ return "Referência de " + QCString(name); }
-
-//////////////////////////////////////////////////////////////////////////
-
};
#endif
diff --git a/src/translator_de.h b/src/translator_de.h
index 8e6ec2c..bf5ce5e 100644
--- a/src/translator_de.h
+++ b/src/translator_de.h
@@ -133,7 +133,7 @@
// 2017/10/12 Arnd Weber (arnd dot weber at bafg dot de)
// Beatrix Konz
// - Updated for 1.8.13
-// - Resynced trMemberDataDocumentation() and trFileMembers() to include the
+// - Resynced trMemberDataDocumentation() and trFileMembers() to include the
// boolean switch OPTIMIZE_OUTPUT_FOR_C
// - Replaced "\t" by " "
//
@@ -143,7 +143,7 @@
#ifndef TRANSLATOR_DE_H
#define TRANSLATOR_DE_H
-class TranslatorGerman : public Translator
+class TranslatorGerman : public TranslatorAdapter_1_8_15
{
public:
@@ -1995,7 +1995,7 @@ class TranslatorGerman : public Translator
/*! Used file list for a Java enum */
virtual QCString trEnumGeneratedFromFiles(bool single)
{ QCString result = "Die Dokumentation für diesen enum wurde aus ";
- if (single)
+ if (single)
result += "der folgenden Datei";
else
result += "den folgenden Dateien";
@@ -2254,7 +2254,7 @@ class TranslatorGerman : public Translator
virtual QCString trCustomReference(const char *name)
{ return QCString(name)+"-Referenz"; }
-//////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////
};
diff --git a/src/translator_en.h b/src/translator_en.h
index d12621e..400e59c 100644
--- a/src/translator_en.h
+++ b/src/translator_en.h
@@ -253,6 +253,10 @@ class TranslatorEnglish : public Translator
{
return "Here are the data structures with brief descriptions:";
}
+ else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE))
+ {
+ return "Here are the classes with brief descriptions:";
+ }
else
{
return "Here are the classes, structs, "
@@ -2117,6 +2121,138 @@ class TranslatorEnglish : public Translator
virtual QCString trCustomReference(const char *name)
{ return QCString(name)+" Reference"; }
+ /* Slice */
+ virtual QCString trConstants()
+ {
+ return "Constants";
+ }
+ virtual QCString trConstantDocumentation()
+ {
+ return "Constant Documentation";
+ }
+ virtual QCString trSequences()
+ {
+ return "Sequences";
+ }
+ virtual QCString trSequenceDocumentation()
+ {
+ return "Sequence Documentation";
+ }
+ virtual QCString trDictionaries()
+ {
+ return "Dictionaries";
+ }
+ virtual QCString trDictionaryDocumentation()
+ {
+ return "Dictionary Documentation";
+ }
+ virtual QCString trSliceInterfaces()
+ {
+ return "Interfaces";
+ }
+ virtual QCString trInterfaceIndex()
+ {
+ return "Interface Index";
+ }
+ virtual QCString trInterfaceList()
+ {
+ return "Interface List";
+ }
+ virtual QCString trInterfaceListDescription()
+ {
+ return "Here are the interfaces with brief descriptions:";
+ }
+ virtual QCString trInterfaceHierarchy()
+ {
+ return "Interface Hierarchy";
+ }
+ virtual QCString trInterfaceHierarchyDescription()
+ {
+ return "This inheritance list is sorted roughly, but not completely, alphabetically:";
+ }
+ virtual QCString trInterfaceDocumentation()
+ {
+ return "Interface Documentation";
+ }
+ virtual QCString trStructs()
+ {
+ return "Structs";
+ }
+ virtual QCString trStructIndex()
+ {
+ return "Struct Index";
+ }
+ virtual QCString trStructList()
+ {
+ return "Struct List";
+ }
+ virtual QCString trStructListDescription()
+ {
+ return "Here are the structs with brief descriptions:";
+ }
+ virtual QCString trStructDocumentation()
+ {
+ return "Struct Documentation";
+ }
+ virtual QCString trExceptionIndex()
+ {
+ return "Exception Index";
+ }
+ virtual QCString trExceptionList()
+ {
+ return "Exception List";
+ }
+ virtual QCString trExceptionListDescription()
+ {
+ return "Here are the exceptions with brief descriptions:";
+ }
+ virtual QCString trExceptionHierarchy()
+ {
+ return "Exception Hierarchy";
+ }
+ virtual QCString trExceptionHierarchyDescription()
+ {
+ return "This inheritance list is sorted roughly, but not completely, alphabetically:";
+ }
+ virtual QCString trExceptionDocumentation()
+ {
+ return "Exception Documentation";
+ }
+ virtual QCString trCompoundReferenceSlice(const char *clName, ClassDef::CompoundType compType, bool isLocal)
+ {
+ QCString result=(QCString)clName;
+ if (isLocal) result+=" Local";
+ switch(compType)
+ {
+ case ClassDef::Class: result+=" Class"; break;
+ case ClassDef::Struct: result+=" Struct"; break;
+ case ClassDef::Union: result+=" Union"; break;
+ case ClassDef::Interface: result+=" Interface"; break;
+ case ClassDef::Protocol: result+=" Protocol"; break;
+ case ClassDef::Category: result+=" Category"; break;
+ case ClassDef::Exception: result+=" Exception"; break;
+ default: break;
+ }
+ result+=" Reference";
+ return result;
+ }
+ virtual QCString trOperations()
+ {
+ return "Operations";
+ }
+ virtual QCString trOperationDocumentation()
+ {
+ return "Operation Documentation";
+ }
+ virtual QCString trDataMembers()
+ {
+ return "Data Members";
+ }
+ virtual QCString trDataMemberDocumentation()
+ {
+ return "Data Member Documentation";
+ }
+
//////////////////////////////////////////////////////////////////////////
};
diff --git a/src/translator_es.h b/src/translator_es.h
index 5f89f24..b28ed75 100644
--- a/src/translator_es.h
+++ b/src/translator_es.h
@@ -2057,6 +2057,254 @@ class TranslatorSpanish : public TranslatorAdapter_1_8_15
}
//////////////////////////////////////////////////////////////////////////
+// new since 1.8.15
+//////////////////////////////////////////////////////////////////////////
+
+ /** VHDL design unit hierarchy */
+ virtual QCString trDesignUnitHierarchy()
+ { return "Jerarquía de unidades de diseño"; }
+ /** VHDL design unit list */
+ virtual QCString trDesignUnitList()
+ { return "Lista de unidades de diseño"; }
+ /** VHDL design unit members */
+ virtual QCString trDesignUnitMembers()
+ { return "Miembros de las unidades de diseño"; }
+ /** VHDL design unit list description */
+ virtual QCString trDesignUnitListDescription()
+ {
+ return "Aquí hay una lista de todos los miembros de la unidad de diseño con "
+ "enlaces a las entidades a las que pertenecen:";
+ }
+ /** VHDL design unit index */
+ virtual QCString trDesignUnitIndex()
+ { return "Indice de unidades de diseño"; }
+ /** VHDL design units */
+ virtual QCString trDesignUnits()
+ { return "Unidades de Diseño"; }
+ /** VHDL functions/procedures/processes */
+ virtual QCString trFunctionAndProc()
+ { return "Funciones/Procedimientos/Procesos"; }
+ /** VHDL type */
+ virtual QCString trVhdlType(uint64 type,bool single)
+ {
+ switch(type)
+ {
+ case VhdlDocGen::LIBRARY:
+ if (single) return "Libreria";
+ else return "Librerias";
+ case VhdlDocGen::PACKAGE:
+ if (single) return "Paquete";
+ else return "Paquetes";
+ case VhdlDocGen::SIGNAL:
+ if (single) return "Señal";
+ else return "Señales";
+ case VhdlDocGen::COMPONENT:
+ if (single) return "Componente";
+ else return "Componentes";
+ case VhdlDocGen::CONSTANT:
+ if (single) return "Constante";
+ else return "Constantes";
+ case VhdlDocGen::ENTITY:
+ if (single) return "Entidad";
+ else return "Entidades";
+ case VhdlDocGen::TYPE:
+ if (single) return "Tipo";
+ else return "Tipos";
+ case VhdlDocGen::SUBTYPE:
+ if (single) return "Subtipo";
+ else return "Subtipos";
+ case VhdlDocGen::FUNCTION:
+ if (single) return "Función";
+ else return "Funciones";
+ case VhdlDocGen::RECORD:
+ if (single) return "Registro";
+ else return "Registros";
+ case VhdlDocGen::PROCEDURE:
+ if (single) return "Procedimiento";
+ else return "Procedimientos";
+ case VhdlDocGen::ARCHITECTURE:
+ if (single) return "Arquitectura";
+ else return "Arquitecturas";
+ case VhdlDocGen::ATTRIBUTE:
+ if (single) return "Atributo";
+ else return "Atributos";
+ case VhdlDocGen::PROCESS:
+ if (single) return "Proceso";
+ else return "Procesos";
+ case VhdlDocGen::PORT:
+ if (single) return "Puerto";
+ else return "Puertos";
+ case VhdlDocGen::USE:
+ if (single) return "cláusula de uso";
+ else return "Cláusulas de uso";
+ case VhdlDocGen::GENERIC:
+ if (single) return "Genérico";
+ else return "Genéricos";
+ case VhdlDocGen::PACKAGE_BODY:
+ return "Cuerpo del paquete";
+ case VhdlDocGen::UNITS:
+ return "Unidades";
+ case VhdlDocGen::SHAREDVARIABLE:
+ if (single) return "Variable Compartida";
+ else return "Variable Compartidas";
+ case VhdlDocGen::VFILE:
+ if (single) return "Fichero";
+ else return "Ficheros";
+ case VhdlDocGen::GROUP:
+ if (single) return "Grupo";
+ else return "Grupos";
+ case VhdlDocGen::INSTANTIATION:
+ if (single) return "Instanciación";
+ else return "Instanciaciones";
+ case VhdlDocGen::ALIAS:
+ if (single) return "Alias";
+ else return "Aliases";
+ case VhdlDocGen::CONFIG:
+ if (single) return "Configuración";
+ else return "Configuraciones";
+ case VhdlDocGen::MISCELLANEOUS:
+ return "Varios";
+ case VhdlDocGen::UCF_CONST:
+ return "Restricciones";
+ default:
+ return "Clase";
+ }
+ }
+ virtual QCString trCustomReference(const char *name)
+ { return "Referencia"+QCString(name); }
+
+ virtual QCString trConstants()
+ {
+ return "Constantes";
+ }
+ virtual QCString trConstantDocumentation()
+ {
+ return "Documentación de constante";
+ }
+ virtual QCString trSequences()
+ {
+ return "Secuencias";
+ }
+ virtual QCString trSequenceDocumentation()
+ {
+ return "Documentación de secuencia";
+ }
+ virtual QCString trDictionaries()
+ {
+ return "Diccionarios";
+ }
+ virtual QCString trDictionaryDocumentation()
+ {
+ return "Documentación de diccionario";
+ }
+ virtual QCString trSliceInterfaces()
+ {
+ return "Interfaces";
+ }
+ virtual QCString trInterfaceIndex()
+ {
+ return "Indice de interfaces";
+ }
+ virtual QCString trInterfaceList()
+ {
+ return "Lista de interfaces";
+ }
+ virtual QCString trInterfaceListDescription()
+ {
+ return "Aquí están las interfaces con una breve descripción:";
+ }
+ virtual QCString trInterfaceHierarchy()
+ {
+ return "Jerarquía de interfaces";
+ }
+ virtual QCString trInterfaceHierarchyDescription()
+ {
+ return "Este listado de herencia está ordenado de forma aproximada, pero no completamente en orden alfabético:";
+ }
+ virtual QCString trInterfaceDocumentation()
+ {
+ return "Documentación de interfaz";
+ }
+ virtual QCString trStructs()
+ {
+ return "Estructuras";
+ }
+ virtual QCString trStructIndex()
+ {
+ return "Indice de estructuras";
+ }
+ virtual QCString trStructList()
+ {
+ return "Lista de estructuras";
+ }
+ virtual QCString trStructListDescription()
+ {
+ return "Aquí están las estructuras de datos con una breve descripción:";
+ }
+ virtual QCString trStructDocumentation()
+ {
+ return "Documentación estructura";
+ }
+ virtual QCString trExceptionIndex()
+ {
+ return "Indice de excepciones";
+ }
+ virtual QCString trExceptionList()
+ {
+ return "Lista de excepciones";
+ }
+ virtual QCString trExceptionListDescription()
+ {
+ return "Aquí están las excepciones con una breve descripción:";
+ }
+ virtual QCString trExceptionHierarchy()
+ {
+ return "Jerarquía de excepciones";
+ }
+ virtual QCString trExceptionHierarchyDescription()
+ {
+ return "Este listado de herencia está ordenado de forma aproximada, pero no completamente en orden alfabético:";
+ }
+ virtual QCString trExceptionDocumentation()
+ {
+ return "Documentación de excepción";
+ }
+ virtual QCString trCompoundReferenceSlice(const char *clName, ClassDef::CompoundType compType, bool isLocal)
+ {
+ QCString result="Referencia de";
+ switch(compType)
+ {
+ case ClassDef::Class: result+=" la Clase"; break;
+ case ClassDef::Struct: result+=" la Estructura"; break;
+ case ClassDef::Union: result+=" la Unión"; break;
+ case ClassDef::Interface: result+=" la Interfaz"; break;
+ case ClassDef::Protocol: result+="l Protocolo"; break;
+ case ClassDef::Category: result+=" la Categoría"; break;
+ case ClassDef::Exception: result+=" la Excepción"; break;
+ default: break;
+ }
+ if (isLocal) result+=" Local";
+ result+=(QCString)clName;
+ return result;
+ }
+ virtual QCString trOperations()
+ {
+ return "Operaciones";
+ }
+ virtual QCString trOperationDocumentation()
+ {
+ return "Documentación de operación";
+ }
+ virtual QCString trDataMembers()
+ {
+ return "Miembros de datos";
+ }
+ virtual QCString trDataMemberDocumentation()
+ {
+ return "Documentación miembro de datos";
+ }
+
+//////////////////////////////////////////////////////////////////////////
};
diff --git a/src/translator_fr.h b/src/translator_fr.h
index b0fb5b1..f355619 100644
--- a/src/translator_fr.h
+++ b/src/translator_fr.h
@@ -2055,6 +2055,258 @@ class TranslatorFrench : public TranslatorAdapter_1_8_15
}
//////////////////////////////////////////////////////////////////////////
+// new since 1.8.15
+//////////////////////////////////////////////////////////////////////////
+
+ /** VHDL design unit hierarchy */
+ virtual QCString trDesignUnitHierarchy()
+ { return "Hiérarchie des unités de conception"; }
+ /** VHDL design unit list */
+ virtual QCString trDesignUnitList()
+ { return "Liste des unités de conception"; }
+ /** VHDL design unit members */
+ virtual QCString trDesignUnitMembers()
+ { return "Membres des unités de conception"; }
+ /** VHDL design unit list description */
+ virtual QCString trDesignUnitListDescription()
+ {
+ return "Liste de tous les membres des unités de conception avec liens vers "
+ "les entités auxquelles ils appartiennent :";
+ }
+ /** VHDL design unit index */
+ virtual QCString trDesignUnitIndex()
+ { return "Index des unités de conception"; }
+ /** VHDL design units */
+ virtual QCString trDesignUnits()
+ { return "Unités de conception"; }
+ /** VHDL functions/procedures/processes */
+ virtual QCString trFunctionAndProc()
+ { return "Fonctions/Procédures/Processes"; }
+ /** VHDL type */
+ virtual QCString trVhdlType(uint64 type,bool single)
+ {
+ switch(type)
+ {
+ case VhdlDocGen::LIBRARY:
+ if (single) return "Librairie";
+ else return "Librairies";
+ case VhdlDocGen::PACKAGE:
+ if (single) return "Paquetage";
+ else return "Paquetages";
+ case VhdlDocGen::SIGNAL:
+ if (single) return "Signal";
+ else return "Signaux";
+ case VhdlDocGen::COMPONENT:
+ if (single) return "Composant";
+ else return "Composants";
+ case VhdlDocGen::CONSTANT:
+ if (single) return "Constante";
+ else return "Constantes";
+ case VhdlDocGen::ENTITY:
+ if (single) return "Entité";
+ else return "Entités";
+ case VhdlDocGen::TYPE:
+ if (single) return "Type";
+ else return "Types";
+ case VhdlDocGen::SUBTYPE:
+ if (single) return "Sous-type";
+ else return "Sous-types";
+ case VhdlDocGen::FUNCTION:
+ if (single) return "Fonction";
+ else return "Fonctions";
+ case VhdlDocGen::RECORD:
+ if (single) return "Enregistrement";
+ else return "Enregistrements";
+ case VhdlDocGen::PROCEDURE:
+ if (single) return "Procédure";
+ else return "Procédures";
+ case VhdlDocGen::ARCHITECTURE:
+ if (single) return "Architecture";
+ else return "Architectures";
+ case VhdlDocGen::ATTRIBUTE:
+ if (single) return "Attribut";
+ else return "Attributs";
+ case VhdlDocGen::PROCESS:
+ if (single) return "Process";
+ else return "Processes";
+ case VhdlDocGen::PORT:
+ if (single) return "Port";
+ else return "Ports";
+ case VhdlDocGen::USE:
+ if (single) return "Clause d'utilisation";
+ else return "Clauses d'utilisation";
+ case VhdlDocGen::GENERIC:
+ if (single) return "Generique";
+ else return "Generiques";
+ case VhdlDocGen::PACKAGE_BODY:
+ return "Corps du paquetage";
+ case VhdlDocGen::UNITS:
+ return "Unités";
+ case VhdlDocGen::SHAREDVARIABLE:
+ if (single) return "Variable partagée";
+ else return "Variables partagées";
+ case VhdlDocGen::VFILE:
+ if (single) return "Fichier";
+ else return "Fichiers";
+ case VhdlDocGen::GROUP:
+ if (single) return "Groupe";
+ else return "Groupes";
+ case VhdlDocGen::INSTANTIATION:
+ if (single) return "Instanciation";
+ else return "Instanciations";
+ case VhdlDocGen::ALIAS:
+ if (single) return "Alias";
+ else return "Alias";
+ case VhdlDocGen::CONFIG:
+ if (single) return "Configuration";
+ else return "Configurations";
+ case VhdlDocGen::MISCELLANEOUS:
+ return "Divers";
+ case VhdlDocGen::UCF_CONST:
+ return "Contraintes";
+ default:
+ return "Classe";
+ }
+ }
+ virtual QCString trCustomReference(const char *name)
+ { return QCString("Référence ") + QCString(name); }
+
+ virtual QCString trConstants()
+ {
+ return "Constantes";
+ }
+ virtual QCString trConstantDocumentation()
+ {
+ return "Documentation des constantes";
+ }
+ virtual QCString trSequences()
+ {
+ return "Séquences";
+ }
+ virtual QCString trSequenceDocumentation()
+ {
+ return "Documentation des séquences";
+ }
+ virtual QCString trDictionaries()
+ {
+ return "Dictionnaires";
+ }
+ virtual QCString trDictionaryDocumentation()
+ {
+ return "Documentation des dictionnaires";
+ }
+ virtual QCString trSliceInterfaces()
+ {
+ return "Interfaces";
+ }
+ virtual QCString trInterfaceIndex()
+ {
+ return "Index des interfaces";
+ }
+ virtual QCString trInterfaceList()
+ {
+ return "Liste des interfaces";
+ }
+ virtual QCString trInterfaceListDescription()
+ {
+ return "Liste des interfaces avec une brève description :";
+ }
+ virtual QCString trInterfaceHierarchy()
+ {
+ return "Hiérarchies des interfaces";
+ }
+ virtual QCString trInterfaceHierarchyDescription()
+ {
+ return "Cette liste d'héritage est classée approximativement par ordre alphabétique :";
+ }
+ virtual QCString trInterfaceDocumentation()
+ {
+ return "Documentation des interfaces";
+ }
+ virtual QCString trStructs()
+ {
+ return "Structures";
+ }
+ virtual QCString trStructIndex()
+ {
+ return "Index des structures";
+ }
+ virtual QCString trStructList()
+ {
+ return "Liste des structures";
+ }
+ virtual QCString trStructListDescription()
+ {
+ return "Liste des structures avec une brève description :";
+ }
+ virtual QCString trStructDocumentation()
+ {
+ return "Documentation des structures";
+ }
+ virtual QCString trExceptionIndex()
+ {
+ return "Index des exceptions";
+ }
+ virtual QCString trExceptionList()
+ {
+ return "Liste des exceptions";
+ }
+ virtual QCString trExceptionListDescription()
+ {
+ return "Liste des exceptions avec une brève description :";
+ }
+ virtual QCString trExceptionHierarchy()
+ {
+ return "Hiérarchies des exceptions";
+ }
+ virtual QCString trExceptionHierarchyDescription()
+ {
+ return "Cette liste d'héritage est classée approximativement par ordre alphabétique :";
+ }
+ virtual QCString trExceptionDocumentation()
+ {
+ return "Documentation des exceptions";
+ }
+ virtual QCString trCompoundReferenceSlice(const char *clName, ClassDef::CompoundType compType, bool isLocal)
+ {
+ QCString result = "Référence de ";
+
+ switch(compType)
+ {
+ case ClassDef::Class: result+="la classe "; break;
+ case ClassDef::Struct: result+="la structure "; break;
+ case ClassDef::Interface: result+="l'interface "; break;
+ case ClassDef::Exception: result+="l'exception "; break;
+ default: break;
+ }
+
+ if(isLocal)
+ {
+ result += "locale ";
+ }
+
+ result += (QCString)clName;
+
+ return result;
+ }
+ virtual QCString trOperations()
+ {
+ return "Opérations";
+ }
+ virtual QCString trOperationDocumentation()
+ {
+ return "Documentation des opérations";
+ }
+ virtual QCString trDataMembers()
+ {
+ return "Champs de données";
+ }
+ virtual QCString trDataMemberDocumentation()
+ {
+ return "Documentation des champs de données";
+ }
+
+//////////////////////////////////////////////////////////////////////////
};
diff --git a/src/translator_nl.h b/src/translator_nl.h
index c0c8c9b..7cecc7d 100644
--- a/src/translator_nl.h
+++ b/src/translator_nl.h
@@ -1709,7 +1709,82 @@ class TranslatorDutch : public Translator
virtual QCString trCustomReference(const char *name)
{ return QCString(name)+" Referentie"; }
-//////////////////////////////////////////////////////////////////////////
+ /* Slice */
+ virtual QCString trConstants()
+ { return "Konstanten"; }
+ virtual QCString trConstantDocumentation()
+ { return "Documentatie van konstanten"; }
+ virtual QCString trSequences()
+ { return "Reeksen"; }
+ virtual QCString trSequenceDocumentation()
+ { return "Documentatie van reeksen"; }
+ virtual QCString trDictionaries()
+ { return "Vertalingslijsten"; }
+ virtual QCString trDictionaryDocumentation()
+ { return "Documentatie van vertalingslijsten"; }
+ virtual QCString trSliceInterfaces()
+ { return "Interfaces"; }
+ virtual QCString trInterfaceIndex()
+ { return "Index van interfaces"; }
+ virtual QCString trInterfaceList()
+ { return "Lijst van interfaces"; }
+ virtual QCString trInterfaceListDescription()
+ { return "Hieronder volgt de lijst met alle interfaces, elk met een korte beschrijving:"; }
+ virtual QCString trInterfaceHierarchy()
+ { return "Interface Hi&euml;rarchie"; }
+ virtual QCString trInterfaceHierarchyDescription()
+ { return "Deze inheritance lijst is min of meer alfabetisch gesorteerd:"; }
+ virtual QCString trInterfaceDocumentation()
+ { return "Documentatie van interfaces"; }
+ virtual QCString trStructs()
+ { return "Structs"; }
+ virtual QCString trStructIndex()
+ { return "Index van struct"; }
+ virtual QCString trStructList()
+ { return "Lijst van struct"; }
+ virtual QCString trStructListDescription()
+ { return "Hieronder volgt de lijst met alle structs, elk met een korte beschrijving:"; }
+ virtual QCString trStructDocumentation()
+ { return "Documentatie van structs"; }
+ virtual QCString trExceptionIndex()
+ { return "Index van exceptions"; }
+ virtual QCString trExceptionList()
+ { return "Lijst van exceptions"; }
+ virtual QCString trExceptionListDescription()
+ { return "Hieronder volgt de lijst met alle exeptions, elk met een korte beschrijving:"; }
+ virtual QCString trExceptionHierarchy()
+ { return "Exception Hi&euml;rarchie"; }
+ virtual QCString trExceptionHierarchyDescription()
+ { return "Deze inheritance lijst is min of meer alfabetisch gesorteerd:"; }
+ virtual QCString trExceptionDocumentation()
+ { return "Documentatie van exceptions"; }
+ virtual QCString trCompoundReferenceSlice(const char *clName, ClassDef::CompoundType compType, bool isLocal)
+ {
+ QCString result=(QCString)clName;
+ if (isLocal) result+=" Lokale";
+ switch(compType)
+ {
+ case ClassDef::Class: result+=" Class"; break;
+ case ClassDef::Struct: result+=" Struct"; break;
+ case ClassDef::Union: result+=" Union"; break;
+ case ClassDef::Interface: result+=" Interface"; break;
+ case ClassDef::Protocol: result+=" Protocol"; break;
+ case ClassDef::Category: result+=" Category"; break;
+ case ClassDef::Exception: result+=" Exception"; break;
+ default: break;
+ }
+ result+=" Referentie";
+ return result;
+ }
+ virtual QCString trOperations()
+ { return "Bewerkingen"; }
+ virtual QCString trOperationDocumentation()
+ { return "Documentatie van bewerkingen"; }
+ virtual QCString trDataMembers()
+ { return "Data members"; }
+ virtual QCString trDataMemberDocumentation()
+ { return "Documentatie van data members"; }
+ //////////////////////////////////////////////////////////////////////////
};
#endif
diff --git a/src/translator_pt.h b/src/translator_pt.h
index 2506f7f..23faf7f 100644
--- a/src/translator_pt.h
+++ b/src/translator_pt.h
@@ -57,7 +57,7 @@
#define TRANSLATOR_PT_H
-class TranslatorPortuguese : public Translator
+class TranslatorPortuguese : public TranslatorAdapter_1_8_15
{
public:
@@ -2138,9 +2138,7 @@ class TranslatorPortuguese : public Translator
virtual QCString trCustomReference(const char *name)
{ return "Referência de " + QCString(name); }
-//////////////////////////////////////////////////////////////////////////
-
-//////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////
};
#endif
diff --git a/src/types.h b/src/types.h
index d6f0342..4d305b6 100644
--- a/src/types.h
+++ b/src/types.h
@@ -56,7 +56,8 @@ enum SrcLangExt
SrcLangExt_XML = 0x04000,
SrcLangExt_Tcl = 0x08000,
SrcLangExt_Markdown = 0x10000,
- SrcLangExt_SQL = 0x20000
+ SrcLangExt_SQL = 0x20000,
+ SrcLangExt_Slice = 0x40000
};
/** Grouping info */
@@ -192,15 +193,20 @@ enum MemberListType
MemberListType_interfaceMembers = 71 + MemberListType_detailedLists,
MemberListType_services = 72,
MemberListType_serviceMembers = 73 + MemberListType_detailedLists,
+
+ MemberListType_decSequenceMembers = 74 + MemberListType_declarationLists,
+ MemberListType_docSequenceMembers = 75 + MemberListType_documentationLists,
+ MemberListType_decDictionaryMembers = 76 + MemberListType_declarationLists,
+ MemberListType_docDictionaryMembers = 77 + MemberListType_documentationLists
};
-enum MemberType
-{
+enum MemberType
+{
MemberType_Define,
- MemberType_Function,
- MemberType_Variable,
- MemberType_Typedef,
- MemberType_Enumeration,
+ MemberType_Function,
+ MemberType_Variable,
+ MemberType_Typedef,
+ MemberType_Enumeration,
MemberType_EnumValue,
MemberType_Signal,
MemberType_Slot,
@@ -210,6 +216,8 @@ enum MemberType
MemberType_Event,
MemberType_Interface,
MemberType_Service,
+ MemberType_Sequence,
+ MemberType_Dictionary
};
enum FortranFormat
diff --git a/src/util.cpp b/src/util.cpp
index 7371026..819903c 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -333,14 +333,15 @@ int guessSection(const char *name)
n.right(4)==".xml" ||
n.right(4)==".sql"
) return Entry::SOURCE_SEC;
- if (n.right(2)==".h" || // header
- n.right(3)==".hh" ||
- n.right(4)==".hxx" ||
- n.right(4)==".hpp" ||
- n.right(4)==".h++" ||
- n.right(4)==".idl" ||
- n.right(4)==".ddl" ||
- n.right(5)==".pidl"
+ if (n.right(2)==".h" || // header
+ n.right(3)==".hh" ||
+ n.right(4)==".hxx" ||
+ n.right(4)==".hpp" ||
+ n.right(4)==".h++" ||
+ n.right(4)==".idl" ||
+ n.right(4)==".ddl" ||
+ n.right(5)==".pidl" ||
+ n.right(4)==".ice"
) return Entry::HEADER_SEC;
return 0;
}
@@ -6638,6 +6639,8 @@ PageDef *addRelatedPage(const char *name,const QCString &ptitle,
// append documentation block to the page.
pd->setDocumentation(doc,fileName,startLine);
//printf("Adding page docs `%s' pi=%p name=%s\n",doc.data(),pd,name);
+ // append (x)refitems to the page.
+ pd->setRefItems(sli);
}
else // new page
{
@@ -6927,7 +6930,7 @@ void filterLatexString(FTextStream &t,const char *str,
}
}
-QCString latexEscapeLabelName(const char *s,bool insideTabbing)
+QCString latexEscapeLabelName(const char *s)
{
QGString result;
QCString tmp(qstrlen(s)+1);
@@ -6957,14 +6960,14 @@ QCString latexEscapeLabelName(const char *s,bool insideTabbing)
p++;
}
tmp[i]=0;
- filterLatexString(t,tmp.data(),insideTabbing);
+ filterLatexString(t,tmp,TRUE);
break;
}
}
return result.data();
}
-QCString latexEscapeIndexChars(const char *s,bool insideTabbing)
+QCString latexEscapeIndexChars(const char *s)
{
QGString result;
QCString tmp(qstrlen(s)+1);
@@ -6995,7 +6998,7 @@ QCString latexEscapeIndexChars(const char *s,bool insideTabbing)
p++;
}
tmp[i]=0;
- filterLatexString(t,tmp.data(),insideTabbing);
+ filterLatexString(t,tmp.data(),TRUE);
break;
}
}
@@ -7026,6 +7029,25 @@ QCString latexEscapePDFString(const char *s)
return result.data();
}
+QCString latexFilterURL(const char *s)
+{
+ QGString result;
+ FTextStream t(&result);
+ const char *p=s;
+ char c;
+ while ((c=*p++))
+ {
+ switch (c)
+ {
+ case '#': t << "\\#"; break;
+ default:
+ t << c;
+ break;
+ }
+ }
+ return result.data();
+}
+
QCString rtfFormatBmkStr(const char *name)
{
@@ -7236,6 +7258,7 @@ g_lang2extMap[] =
{ "objective-c", "c", SrcLangExt_ObjC },
{ "c", "c", SrcLangExt_Cpp },
{ "c++", "c", SrcLangExt_Cpp },
+ { "slice", "c", SrcLangExt_Slice },
{ "python", "python", SrcLangExt_Python },
{ "fortran", "fortran", SrcLangExt_Fortran },
{ "fortranfree", "fortranfree", SrcLangExt_Fortran },
@@ -7341,6 +7364,7 @@ void initDefaultExtensionMapping()
updateLanguageMapping(".qsf", "vhdl");
updateLanguageMapping(".md", "md");
updateLanguageMapping(".markdown", "md");
+ updateLanguageMapping(".ice", "slice");
}
void addCodeOnlyMappings()
@@ -8374,6 +8398,7 @@ QCString langToString(SrcLangExt lang)
case SrcLangExt_SQL: return "SQL";
case SrcLangExt_Tcl: return "Tcl";
case SrcLangExt_Markdown: return "Markdown";
+ case SrcLangExt_Slice: return "Slice";
}
return "Unknown";
}
@@ -8505,12 +8530,9 @@ bool fileVisibleInIndex(FileDef *fd,bool &genSourceFile)
void addDocCrossReference(MemberDef *src,MemberDef *dst)
{
- static bool referencedByRelation = Config_getBool(REFERENCED_BY_RELATION);
- static bool referencesRelation = Config_getBool(REFERENCES_RELATION);
-
//printf("--> addDocCrossReference src=%s,dst=%s\n",src->name().data(),dst->name().data());
if (dst->isTypedef() || dst->isEnumerate()) return; // don't add types
- if ((referencedByRelation || dst->hasCallerGraph()) &&
+ if ((dst->hasReferencedByRelation() || dst->hasCallerGraph()) &&
src->showInCallGraph()
)
{
@@ -8526,7 +8548,7 @@ void addDocCrossReference(MemberDef *src,MemberDef *dst)
mdDecl->addSourceReferencedBy(src);
}
}
- if ((referencesRelation || src->hasCallGraph()) &&
+ if ((src->hasReferencesRelation() || src->hasCallGraph()) &&
src->showInCallGraph()
)
{
@@ -8613,7 +8635,7 @@ uint getUtf8CodeToUpper( const QCString& s, int idx )
//--------------------------------------------------------------------------------------
-bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses)
+bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct)
{
if (nd->getNamespaceSDict())
{
@@ -8625,21 +8647,41 @@ bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses)
{
return TRUE;
}
- else if (namespaceHasVisibleChild(cnd,includeClasses))
+ else if (namespaceHasVisibleChild(cnd,includeClasses,filterClasses,ct))
{
return TRUE;
}
}
}
- if (includeClasses && nd->getClassSDict())
+ if (includeClasses)
{
- ClassSDict::Iterator cli(*nd->getClassSDict());
- ClassDef *cd;
- for (;(cd=cli.current());++cli)
+ ClassSDict *d = nd->getClassSDict();
+ if (filterClasses)
{
- if (cd->isLinkableInProject() && cd->templateMaster()==0)
- {
- return TRUE;
+ if (ct == ClassDef::Interface)
+ {
+ d = nd->getInterfaceSDict();
+ }
+ else if (ct == ClassDef::Struct)
+ {
+ d = nd->getStructSDict();
+ }
+ else if (ct == ClassDef::Exception)
+ {
+ d = nd->getExceptionSDict();
+ }
+ }
+
+ if (d)
+ {
+ ClassSDict::Iterator cli(*d);
+ ClassDef *cd;
+ for (;(cd=cli.current());++cli)
+ {
+ if (cd->isLinkableInProject() && cd->templateMaster()==0)
+ {
+ return TRUE;
+ }
}
}
}
diff --git a/src/util.h b/src/util.h
index 2ee8b17..3305332 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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.
*
@@ -18,7 +18,7 @@
#ifndef UTIL_H
#define UTIL_H
-/*! \file
+/*! \file
* \brief A bunch of utility functions.
*/
@@ -26,6 +26,8 @@
#include <ctype.h>
#include "types.h"
#include "sortdict.h"
+#include "docparser.h"
+#include "classdef.h"
//--------------------------------------------------------------------
@@ -69,7 +71,7 @@ class TextGeneratorIntf
virtual void writeBreak(int indent) const = 0;
virtual void writeLink(const char *extRef,const char *file,
const char *anchor,const char *text
- ) const = 0;
+ ) const = 0;
};
/** Implements TextGeneratorIntf for an OutputDocInterface stream. */
@@ -138,11 +140,11 @@ QCString fileToString(const char *name,bool filter=FALSE,bool isSourceCode=FALSE
QCString dateToString(bool);
bool getDefs(const QCString &scopeName,
- const QCString &memberName,
- const char *,
- MemberDef *&md,
+ const QCString &memberName,
+ const char *,
+ MemberDef *&md,
ClassDef *&cd,
- FileDef *&fd,
+ FileDef *&fd,
NamespaceDef *&nd,
GroupDef *&gd,
bool forceEmptyScope=FALSE,
@@ -260,7 +262,7 @@ void initClassHierarchy(ClassSDict *cl);
bool hasVisibleRoot(BaseClassList *bcl);
bool classHasVisibleChildren(ClassDef *cd);
-bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses);
+bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct);
bool classVisibleInIndex(ClassDef *cd);
int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level=0);
@@ -345,9 +347,10 @@ void filterLatexString(FTextStream &t,const char *str,
bool insideItem=FALSE,
bool keepSpaces=FALSE);
-QCString latexEscapeLabelName(const char *s,bool insideTabbing);
-QCString latexEscapeIndexChars(const char *s,bool insideTabbing);
+QCString latexEscapeLabelName(const char *s);
+QCString latexEscapeIndexChars(const char *s);
QCString latexEscapePDFString(const char *s);
+QCString latexFilterURL(const char *s);
QCString rtfFormatBmkStr(const char *name);
@@ -391,7 +394,7 @@ SrcLangExt getLanguageFromFileName(const QCString& fileName);
void initDefaultExtensionMapping();
void addCodeOnlyMappings();
-MemberDef *getMemberFromSymbol(Definition *scope,FileDef *fileScope,
+MemberDef *getMemberFromSymbol(Definition *scope,FileDef *fileScope,
const char *n);
bool checkIfTypedef(Definition *scope,FileDef *fileScope,const char *n);
@@ -487,4 +490,3 @@ void incUsedTableLevels();
void decUsedTableLevels();
#endif
-
diff --git a/src/vhdlcode.l b/src/vhdlcode.l
index 68dcafb..ee0731f 100644
--- a/src/vhdlcode.l
+++ b/src/vhdlcode.l
@@ -370,7 +370,7 @@ static void codifyLines(const char *text,const char *cl=0,bool classlink=FALSE,b
//g_code->codify(sp);
if (comment)
{
- writeFont("keyword",line.data());
+ writeFont("comment",line.data());
}
else
{
@@ -381,7 +381,7 @@ static void codifyLines(const char *text,const char *cl=0,bool classlink=FALSE,b
else
{
if (comment)
- writeFont("keyword",sp);
+ writeFont("comment",sp);
else
writeWord(sp,cl,classlink);
done=TRUE;
@@ -1478,11 +1478,11 @@ XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI
writeFont("keyword",vhdlcodeYYtext);
}
-<Bases>^{B}*{XILINX}[^\n]* {
- writeWord(yytext);
- //codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE);
- }
-
+<Bases>^{B}*{XILINX}/[^a-zA-Z0-9_] {
+ writeWord(yytext);
+ //codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE);
+ }
+
<Bases>^{B}*"set_"[^\n]* {
writeWord(yytext);
}
@@ -1497,37 +1497,38 @@ XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI
}
<*>\n{TEXTT} { // found normal or special comment on its own line
- QCString text(vhdlcodeYYtext);
- int i=text.find("--");
- if (text.mid(i,3)=="--!" && // hide special comment
- Config_getBool(STRIP_CODE_COMMENTS))
- {
- g_yyLineNr++; // skip complete line
- }
- else // normal comment
- {
- // startFontClass("keyword");
- codifyLines(text,0,FALSE,TRUE);
- // endFontClass();
- }
+ QCString text(vhdlcodeYYtext);
+ int i=text.find("--");
+ if (text.mid(i,3)=="--!") // && // hide special comment
+ {
+ if (!Config_getBool(STRIP_CODE_COMMENTS))
+ {
+ codifyLines(text,0,FALSE,TRUE);
+ }
+ g_yyLineNr++; // skip complete line
+ }
+ else // normal comment
+ {
+ codifyLines(text,0,FALSE,TRUE);
+ }
}
<*>{TEXTT} { // found normal or special comment after something
- QCString text(vhdlcodeYYtext);
- int i=text.find("--");
- if (text.mid(i,3)=="--!" &&
- Config_getBool(STRIP_CODE_COMMENTS))
- {
- // hide special comment
- }
- else // normal comment
- {
- // startFontClass("keyword");
- codifyLines(text,0,FALSE,TRUE);
- // endFontClass();
- }
+ QCString text(vhdlcodeYYtext);
+ int i=text.find("--");
+ if (text.mid(i,3)=="--!")
+ {
+ // hide special comment
+ if (!Config_getBool(STRIP_CODE_COMMENTS))
+ {
+ codifyLines(text,0,FALSE,TRUE);
+ }
+ }
+ else // normal comment
+ {
+ codifyLines(text,0,FALSE,TRUE);
+ }
}
-
%%
/*@ ----------------------------------------------------------------------------
diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp
index 287565b..7700295 100644
--- a/src/vhdldocgen.cpp
+++ b/src/vhdldocgen.cpp
@@ -602,7 +602,7 @@ const char* g_vhdlKeyWordMap1[] =
{
"natural","unsigned","signed","string","boolean", "bit","bit_vector","character",
"std_ulogic","std_ulogic_vector","std_logic","std_logic_vector","integer",
- "real","float","ufixed","sfixed","time",0
+ "real","float","ufixed","sfixed","time","positive",0
};
// logic
@@ -667,7 +667,7 @@ const char* g_vhdlKeyWordMap3[] =
QCString* VhdlDocGen::findKeyWord(const QCString& tmp)
{
static QCString vhdlkeyword("vhdlkeyword");
- static QCString vhdltype("comment");
+ static QCString vhdltype("keywordtype");
static QCString vhdllogic("vhdllogic");
static QCString preprocessor("keywordflow");
@@ -2466,8 +2466,8 @@ void VhdlDocGen::writeSource(MemberDef *mdef,OutputList& ol,QCString & cname)
if (cname.isEmpty()) return;
mdef->writeSourceDef(ol,cname);
- mdef->writeSourceRefs(ol,cname);
- mdef->writeSourceReffedBy(ol,cname);
+ if (mdef->hasReferencesRelation()) mdef->writeSourceRefs(ol,cname);
+ if (mdef->hasReferencedByRelation()) mdef->writeSourceReffedBy(ol,cname);
}
@@ -2990,7 +2990,8 @@ ferr:
Public, Normal, cur->stat,Member,
MemberType_Variable,
0,
- 0);
+ 0,
+ "");
if (ar->getOutputFileBase())
{
diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp
index 525dbf5..4aa81ca 100644
--- a/src/xmldocvisitor.cpp
+++ b/src/xmldocvisitor.cpp
@@ -31,6 +31,7 @@
#include "filename.h"
#include "config.h"
#include "htmlentity.h"
+#include "emoji.h"
static void visitCaption(XmlDocVisitor *parent, QList<DocNode> children)
{
@@ -39,10 +40,10 @@ static void visitCaption(XmlDocVisitor *parent, QList<DocNode> children)
for (cli.toFirst();(n=cli.current());++cli) n->accept(parent);
}
-static void visitPreStart(FTextStream &t, const char *cmd, const bool doCaption,
+static void visitPreStart(FTextStream &t, const char *cmd, bool doCaption,
XmlDocVisitor *parent, QList<DocNode> children,
const QCString &name, bool writeType, DocImage::Type type, const QCString &width,
- const QCString &height)
+ const QCString &height, bool inlineImage = FALSE)
{
t << "<" << cmd;
if (writeType)
@@ -69,6 +70,7 @@ static void visitPreStart(FTextStream &t, const char *cmd, const bool doCaption,
{
t << " height=\"" << convertToXML(height) << "\"";
}
+ if (inlineImage) t << " inline=\"yes\">";
if (doCaption)
{
t << " caption=\"";
@@ -133,6 +135,20 @@ void XmlDocVisitor::visit(DocSymbol *s)
}
}
+void XmlDocVisitor::visit(DocEmoji *s)
+{
+ if (m_hide) return;
+ const char *res = EmojiEntityMapper::instance()->xml(s->emoji());
+ if (res)
+ {
+ m_t << res;
+ }
+ else
+ {
+ err("XML: non supported Emoji-entity found: %s\n",EmojiEntityMapper::instance()->html(s->emoji()));
+ }
+}
+
void XmlDocVisitor::visit(DocURL *u)
{
if (m_hide) return;
@@ -494,7 +510,7 @@ void XmlDocVisitor::visitPre(DocPara *)
void XmlDocVisitor::visitPost(DocPara *)
{
if (m_hide) return;
- m_t << "</para>";
+ m_t << "</para>" << endl;
}
void XmlDocVisitor::visitPre(DocRoot *)
@@ -773,7 +789,7 @@ void XmlDocVisitor::visitPre(DocImage *img)
{
baseName=baseName.right(baseName.length()-i-1);
}
- visitPreStart(m_t, "image", FALSE, this, img->children(), baseName, TRUE, img->type(), img->width(), img->height());
+ visitPreStart(m_t, "image", FALSE, this, img->children(), baseName, TRUE, img->type(), img->width(), img->height(), img ->isInlineImage());
// copy the image to the output dir
FileDef *fd;
diff --git a/src/xmldocvisitor.h b/src/xmldocvisitor.h
index c65688f..c2c6537 100644
--- a/src/xmldocvisitor.h
+++ b/src/xmldocvisitor.h
@@ -41,6 +41,7 @@ class XmlDocVisitor : public DocVisitor
void visit(DocLinkedWord *);
void visit(DocWhiteSpace *);
void visit(DocSymbol *);
+ void visit(DocEmoji *);
void visit(DocURL *);
void visit(DocLineBreak *);
void visit(DocHorRuler *);
diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp
index be866a2..4b12757 100644
--- a/src/xmlgen.cpp
+++ b/src/xmlgen.cpp
@@ -97,6 +97,8 @@ class XmlSectionMapper : public QIntDict<char>
insert(MemberListType_decDefineMembers,"define");
insert(MemberListType_decProtoMembers,"prototype");
insert(MemberListType_decTypedefMembers,"typedef");
+ insert(MemberListType_decSequenceMembers,"sequence");
+ insert(MemberListType_decDictionaryMembers,"dictionary");
insert(MemberListType_decEnumMembers,"enum");
insert(MemberListType_decFuncMembers,"func");
insert(MemberListType_decVarMembers,"var");
@@ -222,146 +224,117 @@ class TextGeneratorXMLImpl : public TextGeneratorIntf
/** Generator for producing XML formatted source code. */
-class XMLCodeGenerator : public CodeOutputInterface
+void XMLCodeGenerator::codify(const char *text)
{
- public:
-
- XMLCodeGenerator(FTextStream &t) : m_t(t), m_lineNumber(-1), m_isMemberRef(FALSE), m_col(0),
- m_insideCodeLine(FALSE), m_normalHLNeedStartTag(TRUE), m_insideSpecialHL(FALSE) {}
- virtual ~XMLCodeGenerator() { }
-
- void codify(const char *text)
- {
- XML_DB(("(codify \"%s\")\n",text));
- if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag)
- {
- m_t << "<highlight class=\"normal\">";
- m_normalHLNeedStartTag=FALSE;
- }
- writeXMLCodeString(m_t,text,m_col);
- }
- void writeCodeLink(const char *ref,const char *file,
- const char *anchor,const char *name,
- const char *tooltip)
- {
- XML_DB(("(writeCodeLink)\n"));
- if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag)
- {
- m_t << "<highlight class=\"normal\">";
- m_normalHLNeedStartTag=FALSE;
- }
- writeXMLLink(m_t,ref,file,anchor,name,tooltip);
- m_col+=qstrlen(name);
- }
- void writeTooltip(const char *, const DocLinkInfo &, const char *,
- const char *, const SourceLinkInfo &, const SourceLinkInfo &
- )
- {
- XML_DB(("(writeToolTip)\n"));
- }
- void startCodeLine(bool)
- {
- XML_DB(("(startCodeLine)\n"));
- m_t << "<codeline";
- if (m_lineNumber!=-1)
- {
- m_t << " lineno=\"" << m_lineNumber << "\"";
- if (!m_refId.isEmpty())
- {
- m_t << " refid=\"" << m_refId << "\"";
- if (m_isMemberRef)
- {
- m_t << " refkind=\"member\"";
- }
- else
- {
- m_t << " refkind=\"compound\"";
- }
- }
- if (!m_external.isEmpty())
- {
- m_t << " external=\"" << m_external << "\"";
- }
- }
- m_t << ">";
- m_insideCodeLine=TRUE;
- m_col=0;
- }
- void endCodeLine()
- {
- XML_DB(("(endCodeLine)\n"));
- if (!m_insideSpecialHL && !m_normalHLNeedStartTag)
- {
- m_t << "</highlight>";
- m_normalHLNeedStartTag=TRUE;
- }
- m_t << "</codeline>" << endl; // non DocBook
- m_lineNumber = -1;
- m_refId.resize(0);
- m_external.resize(0);
- m_insideCodeLine=FALSE;
- }
- void startFontClass(const char *colorClass)
+ XML_DB(("(codify \"%s\")\n",text));
+ if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag)
+ {
+ m_t << "<highlight class=\"normal\">";
+ m_normalHLNeedStartTag=FALSE;
+ }
+ writeXMLCodeString(m_t,text,m_col);
+}
+void XMLCodeGenerator::writeCodeLink(const char *ref,const char *file,
+ const char *anchor,const char *name,
+ const char *tooltip)
+{
+ XML_DB(("(writeCodeLink)\n"));
+ if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag)
+ {
+ m_t << "<highlight class=\"normal\">";
+ m_normalHLNeedStartTag=FALSE;
+ }
+ writeXMLLink(m_t,ref,file,anchor,name,tooltip);
+ m_col+=qstrlen(name);
+}
+void XMLCodeGenerator::writeTooltip(const char *, const DocLinkInfo &, const char *,
+ const char *, const SourceLinkInfo &, const SourceLinkInfo &
+ )
+{
+ XML_DB(("(writeToolTip)\n"));
+}
+void XMLCodeGenerator::startCodeLine(bool)
+{
+ XML_DB(("(startCodeLine)\n"));
+ m_t << "<codeline";
+ if (m_lineNumber!=-1)
+ {
+ m_t << " lineno=\"" << m_lineNumber << "\"";
+ if (!m_refId.isEmpty())
{
- XML_DB(("(startFontClass)\n"));
- if (m_insideCodeLine && !m_insideSpecialHL && !m_normalHLNeedStartTag)
+ m_t << " refid=\"" << m_refId << "\"";
+ if (m_isMemberRef)
{
- m_t << "</highlight>";
- m_normalHLNeedStartTag=TRUE;
+ m_t << " refkind=\"member\"";
}
- m_t << "<highlight class=\"" << colorClass << "\">"; // non DocBook
- m_insideSpecialHL=TRUE;
- }
- void endFontClass()
- {
- XML_DB(("(endFontClass)\n"));
- m_t << "</highlight>"; // non DocBook
- m_insideSpecialHL=FALSE;
- }
- void writeCodeAnchor(const char *)
- {
- XML_DB(("(writeCodeAnchor)\n"));
- }
- void writeLineNumber(const char *extRef,const char *compId,
- const char *anchorId,int l)
- {
- XML_DB(("(writeLineNumber)\n"));
- // we remember the information provided here to use it
- // at the <codeline> start tag.
- m_lineNumber = l;
- if (compId)
+ else
{
- m_refId=compId;
- if (anchorId) m_refId+=(QCString)"_1"+anchorId;
- m_isMemberRef = anchorId!=0;
- if (extRef) m_external=extRef;
+ m_t << " refkind=\"compound\"";
}
}
- void setCurrentDoc(Definition *,const char *,bool)
- {
- }
- void addWord(const char *,bool)
+ if (!m_external.isEmpty())
{
+ m_t << " external=\"" << m_external << "\"";
}
-
- void finish()
- {
- if (m_insideCodeLine) endCodeLine();
- }
-
- private:
- FTextStream &m_t;
- QCString m_refId;
- QCString m_external;
- int m_lineNumber;
- bool m_isMemberRef;
- int m_col;
-
- bool m_insideCodeLine;
- bool m_normalHLNeedStartTag;
- bool m_insideSpecialHL;
-};
-
+ }
+ m_t << ">";
+ m_insideCodeLine=TRUE;
+ m_col=0;
+}
+void XMLCodeGenerator::endCodeLine()
+{
+ XML_DB(("(endCodeLine)\n"));
+ if (!m_insideSpecialHL && !m_normalHLNeedStartTag)
+ {
+ m_t << "</highlight>";
+ m_normalHLNeedStartTag=TRUE;
+ }
+ m_t << "</codeline>" << endl; // non DocBook
+ m_lineNumber = -1;
+ m_refId.resize(0);
+ m_external.resize(0);
+ m_insideCodeLine=FALSE;
+}
+void XMLCodeGenerator::startFontClass(const char *colorClass)
+{
+ XML_DB(("(startFontClass)\n"));
+ if (m_insideCodeLine && !m_insideSpecialHL && !m_normalHLNeedStartTag)
+ {
+ m_t << "</highlight>";
+ m_normalHLNeedStartTag=TRUE;
+ }
+ m_t << "<highlight class=\"" << colorClass << "\">"; // non DocBook
+ m_insideSpecialHL=TRUE;
+}
+void XMLCodeGenerator::endFontClass()
+{
+ XML_DB(("(endFontClass)\n"));
+ m_t << "</highlight>"; // non DocBook
+ m_insideSpecialHL=FALSE;
+}
+void XMLCodeGenerator::writeCodeAnchor(const char *)
+{
+ XML_DB(("(writeCodeAnchor)\n"));
+}
+void XMLCodeGenerator::writeLineNumber(const char *extRef,const char *compId,
+ const char *anchorId,int l)
+{
+ XML_DB(("(writeLineNumber)\n"));
+ // we remember the information provided here to use it
+ // at the <codeline> start tag.
+ m_lineNumber = l;
+ if (compId)
+ {
+ m_refId=compId;
+ if (anchorId) m_refId+=(QCString)"_1"+anchorId;
+ m_isMemberRef = anchorId!=0;
+ if (extRef) m_external=extRef;
+ }
+}
+void XMLCodeGenerator::finish()
+{
+ if (m_insideCodeLine) endCodeLine();
+}
static void writeTemplateArgumentList(ArgumentList *al,
FTextStream &t,
@@ -554,20 +527,22 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De
bool isFunc=FALSE;
switch (md->memberType())
{
- case MemberType_Define: memType="define"; break;
- case MemberType_Function: memType="function"; isFunc=TRUE; break;
- case MemberType_Variable: memType="variable"; break;
- case MemberType_Typedef: memType="typedef"; break;
- case MemberType_Enumeration: memType="enum"; break;
- case MemberType_EnumValue: ASSERT(0); break;
- case MemberType_Signal: memType="signal"; isFunc=TRUE; break;
- case MemberType_Slot: memType="slot"; isFunc=TRUE; break;
- case MemberType_Friend: memType="friend"; isFunc=TRUE; break;
- case MemberType_DCOP: memType="dcop"; isFunc=TRUE; break;
- case MemberType_Property: memType="property"; break;
- case MemberType_Event: memType="event"; break;
- case MemberType_Interface: memType="interface"; break;
- case MemberType_Service: memType="service"; break;
+ case MemberType_Define: memType="define"; break;
+ case MemberType_Function: memType="function"; isFunc=TRUE; break;
+ case MemberType_Variable: memType="variable"; break;
+ case MemberType_Typedef: memType="typedef"; break;
+ case MemberType_Enumeration: memType="enum"; break;
+ case MemberType_EnumValue: ASSERT(0); break;
+ case MemberType_Signal: memType="signal"; isFunc=TRUE; break;
+ case MemberType_Slot: memType="slot"; isFunc=TRUE; break;
+ case MemberType_Friend: memType="friend"; isFunc=TRUE; break;
+ case MemberType_DCOP: memType="dcop"; isFunc=TRUE; break;
+ case MemberType_Property: memType="property"; break;
+ case MemberType_Event: memType="event"; break;
+ case MemberType_Interface: memType="interface"; break;
+ case MemberType_Service: memType="service"; break;
+ case MemberType_Sequence: memType="sequence"; break;
+ case MemberType_Dictionary: memType="dictionary"; break;
}
ti << " <member refid=\"" << memberOutputFileBase(md)
@@ -1163,7 +1138,7 @@ static void writeInnerNamespaces(const NamespaceSDict *nl,FTextStream &t)
NamespaceDef *nd;
for (nli.toFirst();(nd=nli.current());++nli)
{
- if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymouse scopes
+ if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymous scopes
{
t << " <innernamespace refid=\"" << nd->getOutputFileBase()
<< "\">" << convertToXML(nd->name()) << "</innernamespace>" << endl;
diff --git a/src/xmlgen.h b/src/xmlgen.h
index 0447591..0555546 100644
--- a/src/xmlgen.h
+++ b/src/xmlgen.h
@@ -15,6 +15,48 @@
#ifndef XMLGEN_H
#define XMLGEN_H
+#include "outputgen.h"
+
+class XMLCodeGenerator : public CodeOutputInterface
+{
+ public:
+
+ XMLCodeGenerator(FTextStream &t) : m_t(t), m_lineNumber(-1), m_isMemberRef(FALSE), m_col(0),
+ m_insideCodeLine(FALSE), m_normalHLNeedStartTag(TRUE), m_insideSpecialHL(FALSE) {}
+ virtual ~XMLCodeGenerator() { }
+
+ void codify(const char *text);
+ void writeCodeLink(const char *ref,const char *file,
+ const char *anchor,const char *name,
+ const char *tooltip);
+ void writeTooltip(const char *, const DocLinkInfo &, const char *,
+ const char *, const SourceLinkInfo &, const SourceLinkInfo &
+ );
+ void startCodeLine(bool);
+ void endCodeLine();
+ void startFontClass(const char *colorClass);
+ void endFontClass();
+ void writeCodeAnchor(const char *);
+ void writeLineNumber(const char *extRef,const char *compId,
+ const char *anchorId,int l);
+ void setCurrentDoc(Definition *,const char *,bool){}
+ void addWord(const char *,bool){}
+
+ void finish();
+
+ private:
+ FTextStream &m_t;
+ QCString m_refId;
+ QCString m_external;
+ int m_lineNumber;
+ bool m_isMemberRef;
+ int m_col;
+
+ bool m_insideCodeLine;
+ bool m_normalHLNeedStartTag;
+ bool m_insideSpecialHL;
+};
+
void generateXML();
#endif
diff --git a/templates/html/doxygen.css b/templates/html/doxygen.css
index bee3bb4..c9bf428 100644
--- a/templates/html/doxygen.css
+++ b/templates/html/doxygen.css
@@ -352,7 +352,7 @@ img.formulaDsp {
}
-img.formulaInl {
+img.formulaInl, img.inline {
vertical-align: middle;
}
diff --git a/templates/html/header.html b/templates/html/header.html
index 338d0be..9527936 100644
--- a/templates/html/header.html
+++ b/templates/html/header.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
diff --git a/templates/html/htmlbase.tpl b/templates/html/htmlbase.tpl
index e271d3a..47939fd 100644
--- a/templates/html/htmlbase.tpl
+++ b/templates/html/htmlbase.tpl
@@ -1,5 +1,5 @@
{% block header %}
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
diff --git a/templates/html/htmlsearchresult.tpl b/templates/html/htmlsearchresult.tpl
index b795743..db37a5d 100644
--- a/templates/html/htmlsearchresult.tpl
+++ b/templates/html/htmlsearchresult.tpl
@@ -1,5 +1,5 @@
{# input: baseName #}
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html><head><title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen {{ doxygen.version }}"/>
diff --git a/templates/latex/doxygen.sty b/templates/latex/doxygen.sty
index 4b8c455..cf92712 100644
--- a/templates/latex/doxygen.sty
+++ b/templates/latex/doxygen.sty
@@ -190,6 +190,12 @@
\end{center}%
}
+% Used by @image
+% (only if inline is specified)
+\newenvironment{DoxyInlineImage}{%
+}{%
+}
+
% Used by @attention
\newenvironment{DoxyAttention}[1]{%
\begin{DoxyDesc}{#1}%
diff --git a/testing/009/bug.xml b/testing/009/bug.xml
index a6dfe88..34a411b 100644
--- a/testing/009/bug.xml
+++ b/testing/009/bug.xml
@@ -9,17 +9,16 @@
<para>
<variablelist>
<varlistentry>
- <term><anchor id="bug_1_bug000001"/>Class <ref refid="class_bug" kindref="compound">Bug</ref></term>
+ <term>Class <ref refid="class_bug" kindref="compound">Bug</ref></term>
</varlistentry>
<listitem>
- <para>Class bug. </para>
+ <para><anchor id="bug_1_bug000001"/>Class bug. </para>
</listitem>
<varlistentry>
- <term><anchor id="bug_1_bug000002"/>Member <ref refid="class_bug_1a1f720954dd97cd1203e80501a6eae74c" kindref="member">Bug::foo</ref> ()</term>
+ <term>Member <ref refid="class_bug_1a1f720954dd97cd1203e80501a6eae74c" kindref="member">Bug::foo</ref> ()</term>
</varlistentry>
<listitem>
- <para>Function bug<itemizedlist><listitem><para>list item 1 in bug</para></listitem><listitem><para>list item 2 in bug</para></listitem></itemizedlist>
-</para>
+ <para><anchor id="bug_1_bug000002"/>Function bug<itemizedlist><listitem><para>list item 1 in bug</para></listitem><listitem><para>list item 2 in bug</para></listitem></itemizedlist></para>
</listitem>
</variablelist>
</para>
diff --git a/testing/009/deprecated.xml b/testing/009/deprecated.xml
index 5db2acd..a787015 100644
--- a/testing/009/deprecated.xml
+++ b/testing/009/deprecated.xml
@@ -9,16 +9,16 @@
<para>
<variablelist>
<varlistentry>
- <term><anchor id="deprecated_1_deprecated000001"/>Class <ref refid="class_deprecated" kindref="compound">Deprecated</ref></term>
+ <term>Class <ref refid="class_deprecated" kindref="compound">Deprecated</ref></term>
</varlistentry>
<listitem>
- <para>This class is deprecated </para>
+ <para><anchor id="deprecated_1_deprecated000001"/>This class is deprecated </para>
</listitem>
<varlistentry>
- <term><anchor id="deprecated_1_deprecated000002"/>Member <ref refid="class_deprecated_1a1d5f6803e72c625727e7083d1722dbf9" kindref="member">Deprecated::deprecated</ref> ()</term>
+ <term>Member <ref refid="class_deprecated_1a1d5f6803e72c625727e7083d1722dbf9" kindref="member">Deprecated::deprecated</ref> ()</term>
</varlistentry>
<listitem>
- <para>No not use this function anymore. </para>
+ <para><anchor id="deprecated_1_deprecated000002"/>No not use this function anymore. </para>
</listitem>
</variablelist>
</para>
diff --git a/testing/009/reminders.xml b/testing/009/reminders.xml
index a5c5560..f848e3c 100644
--- a/testing/009/reminders.xml
+++ b/testing/009/reminders.xml
@@ -9,16 +9,16 @@
<para>
<variablelist>
<varlistentry>
- <term><anchor id="reminders_1_reminders000001"/>Class <ref refid="class_reminder" kindref="compound">Reminder</ref></term>
+ <term>Class <ref refid="class_reminder" kindref="compound">Reminder</ref></term>
</varlistentry>
<listitem>
- <para>A reminder </para>
+ <para><anchor id="reminders_1_reminders000001"/>A reminder </para>
</listitem>
<varlistentry>
- <term><anchor id="reminders_1_reminders000002"/>Member <ref refid="class_reminder_1a173b5218bb11287b0e86a550d9f0728d" kindref="member">Reminder::reminder</ref> ()</term>
+ <term>Member <ref refid="class_reminder_1a173b5218bb11287b0e86a550d9f0728d" kindref="member">Reminder::reminder</ref> ()</term>
</varlistentry>
<listitem>
- <para>Need to rework this before the next release. </para>
+ <para><anchor id="reminders_1_reminders000002"/>Need to rework this before the next release. </para>
</listitem>
</variablelist>
</para>
diff --git a/testing/009/test.xml b/testing/009/test.xml
index e206440..828316d 100644
--- a/testing/009/test.xml
+++ b/testing/009/test.xml
@@ -9,16 +9,16 @@
<para>
<variablelist>
<varlistentry>
- <term><anchor id="test_1_test000001"/>Class <ref refid="class_test" kindref="compound">Test</ref></term>
+ <term>Class <ref refid="class_test" kindref="compound">Test</ref></term>
</varlistentry>
<listitem>
- <para>This is part of testing </para>
+ <para><anchor id="test_1_test000001"/>This is part of testing </para>
</listitem>
<varlistentry>
- <term><anchor id="test_1_test000002"/>Member <ref refid="class_test_1a9fc54b716f326514a4c5f434137f4fc0" kindref="member">Test::test</ref> ()</term>
+ <term>Member <ref refid="class_test_1a9fc54b716f326514a4c5f434137f4fc0" kindref="member">Test::test</ref> ()</term>
</varlistentry>
<listitem>
- <para>more things to test. </para>
+ <para><anchor id="test_1_test000002"/>more things to test. </para>
</listitem>
</variablelist>
</para>
diff --git a/testing/009/todo.xml b/testing/009/todo.xml
index 88d050e..394f07d 100644
--- a/testing/009/todo.xml
+++ b/testing/009/todo.xml
@@ -9,16 +9,16 @@
<para>
<variablelist>
<varlistentry>
- <term><anchor id="todo_1_todo000001"/>Class <ref refid="class_todo" kindref="compound">Todo</ref></term>
+ <term>Class <ref refid="class_todo" kindref="compound">Todo</ref></term>
</varlistentry>
<listitem>
- <para>This still needs to be done. </para>
+ <para><anchor id="todo_1_todo000001"/>This still needs to be done. </para>
</listitem>
<varlistentry>
- <term><anchor id="todo_1_todo000002"/>Member <ref refid="class_todo_1a9e70ec9176ac4c1b20e011b4daddc9d8" kindref="member">Todo::todo</ref> ()</term>
+ <term>Member <ref refid="class_todo_1a9e70ec9176ac4c1b20e011b4daddc9d8" kindref="member">Todo::todo</ref> ()</term>
</varlistentry>
<listitem>
- <para>more things to do here </para>
+ <para><anchor id="todo_1_todo000002"/>more things to do here </para>
</listitem>
</variablelist>
</para>
diff --git a/testing/012/citelist.xml b/testing/012/citelist.xml
index 96b94a3..f415968 100644
--- a/testing/012/citelist.xml
+++ b/testing/012/citelist.xml
@@ -9,7 +9,7 @@
<para>
<variablelist>
<varlistentry>
- <term><anchor id="_1CITEREF_knuth79"/>[1]</term>
+ <term><anchor id="citelist_1CITEREF_knuth79"/>[1]</term>
</varlistentry>
<listitem>
<para>Donald<nonbreakablespace/>E. Knuth. <emphasis>Tex and Metafont, New Directions in Typesetting</emphasis>. American Mathematical Society and Digital Press, Stanford, 1979.</para>
diff --git a/testing/README.txt b/testing/README.txt
index 4988a07..39b2345 100644
--- a/testing/README.txt
+++ b/testing/README.txt
@@ -7,7 +7,7 @@ has the same 3 digit number. The directory contains one or more reference
files that are compared against the XML output produced by doxygen. If the
result is the same, there is no regression and the test passes. If there is a
difference the test fails and the difference (in diff -u format) will be shown.
-It is also possible to see whether or not the test can be built to an xhtml set
+It is also possible to see whether or not the test can be built to a xhtml set
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.
@@ -17,6 +17,8 @@ optional parameters:
--doxygen [DOXYGEN] path/name of the doxygen executable
--xmllint [XMLLINT] path/name of the xmllint executable
--id IDS [IDS ...] id of the test to perform
+ --start_id START_ID run tests starting with number n
+ --end_id END_ID run tests ending with number n
--all perform all tests
--inputdir [INPUTDIR]
input directory containing the tests
@@ -24,13 +26,15 @@ optional parameters:
output directory to write the doxygen output to
--noredir disable redirection of doxygen warnings
--xml create xml output and check
+ --rtf create rtf output
+ --docbook create docbook output and check with xmllint
--xhtml create xhtml output and check with xmllint
--pdf create LaTeX output and create pdf from it
+ --subdirs use the configuration parameter CREATE_SUBDIRS=YES
--keep keep result directories
- --cfg CFGS [CFGS ...]
- run test with extra doxygen configuration settings
+ --cfg CFGS [CFGS ...] run test with extra doxygen configuration settings
(the option may be specified multiple times
-In case neither --xml, --pdf or --xhtml is used the default is set to --xml.
+In case neither --xml, --pdf, --rtf, --docbook or --xhtml is used the default is set to --xml.
The runtest.pl has the following dependencies on 3rd party tools:
- python to run the script
diff --git a/testing/runtests.py b/testing/runtests.py
index fa74627..452c36e 100644
--- a/testing/runtests.py
+++ b/testing/runtests.py
@@ -43,6 +43,28 @@ class Tester:
rtnmsg += o
return rtnmsg
+ def cleanup_xmllint_docbook(self,errmsg):
+ # For future work, first get everything valid XML
+ msg = self.cleanup_xmllint(errmsg).split('\n')
+ rtnmsg = ""
+ cnt = 0
+ for o in msg:
+ if (o):
+ if (cnt):
+ cnt -= 1
+ pass
+ elif (o.endswith("does not validate")):
+ pass
+ elif (o.find("no DTD found!")!=-1):
+ pass
+ elif (o.find("is not an NCName")!=-1):
+ cnt = 2
+ else:
+ if (rtnmsg):
+ rtnmsg += '\n'
+ rtnmsg += o
+ return rtnmsg
+
def get_config(self):
config = {}
with open(self.args.inputdir+'/'+self.test,'r') as f:
@@ -53,7 +75,7 @@ class Tester:
value = m.group('value')
if (key=='config'):
value = value.replace('$INPUTDIR',self.args.inputdir)
- #print('key=%s value=%s' % (key,value))
+ # print('key=%s value=%s' % (key,value))
config.setdefault(key, []).append(value)
return config
@@ -74,6 +96,16 @@ class Tester:
print('XML_OUTPUT=%s/out' % self.test_out, file=f)
else:
print('GENERATE_XML=NO', file=f)
+ if (self.args.rtf):
+ print('GENERATE_RTF=YES', file=f)
+ print('RTF_OUTPUT=%s/rtf' % self.test_out, file=f)
+ else:
+ print('GENERATE_RTF=NO', file=f)
+ if (self.args.docbook):
+ print('GENERATE_DOCBOOK=YES', file=f)
+ print('DOCBOOK_OUTPUT=%s/docbook' % self.test_out, file=f)
+ else:
+ print('GENERATE_DOCBOOK=NO', file=f)
if (self.args.xhtml):
print('GENERATE_HTML=YES', file=f)
# HTML_OUTPUT can also be set locally
@@ -82,6 +114,8 @@ class Tester:
if (self.args.pdf):
print('GENERATE_LATEX=YES', file=f)
print('LATEX_OUTPUT=%s/latex' % self.test_out, file=f)
+ if self.args.subdirs:
+ print('CREATE_SUBDIRS=YES', file=f)
if (self.args.cfgs):
for cfg in list(itertools.chain.from_iterable(self.args.cfgs)):
if cfg.find('=') == -1:
@@ -103,7 +137,7 @@ class Tester:
redir=''
if os.system('%s %s/Doxyfile %s' % (self.args.doxygen,self.test_out,redir))!=0:
- print('Error: failed to run %s on %s/Doxyfile' % (self.args.doxygen,self.test_out));
+ print('Error: failed to run %s on %s/Doxyfile' % (self.args.doxygen,self.test_out))
sys.exit(1)
# update the reference data for this test
@@ -146,6 +180,8 @@ class Tester:
failed_xml=False
failed_html=False
failed_latex=False
+ failed_docbook=False
+ failed_rtf=False
msg = ()
# look for files to check against the reference
if self.args.xml:
@@ -155,8 +191,14 @@ class Tester:
check_file='%s/out/%s' % (self.test_out,check)
# check if the file we need to check is actually generated
if not os.path.isfile(check_file):
- msg += ('Non-existing file %s after \'check:\' statement' % check_file,)
- break
+ # try with sub dirs
+ check_file = glob.glob('%s/out/*/*/%s' % (self.test_out,check))
+ if not check_file:
+ check_file='%s/out/%s' % (self.test_out,check)
+ msg += ('Non-existing file %s after \'check:\' statement' % check_file,)
+ break
+ else:
+ check_file = check_file[0]
# convert output to canonical form
data = os.popen('%s --format --noblanks --nowarning %s' % (self.args.xmllint,check_file)).read()
if data:
@@ -177,6 +219,34 @@ class Tester:
xml_output='%s/out' % self.test_out
shutil.rmtree(xml_output,ignore_errors=True)
+ if (self.args.rtf):
+ # no tests defined yet
+ pass
+
+ if (self.args.docbook):
+ docbook_output='%s/docbook' % self.test_out
+ if (sys.platform == 'win32'):
+ redirx=' 2> %s/temp >nul:'%docbook_output
+ else:
+ redirx='2>%s/temp >/dev/null'%docbook_output
+ # For future work, first get everything valid XML
+ # exe_string = '%s --relaxng db/docbook.rng --nonet --postvalid %s/*xml %s % (self.args.xmllint,docbook_output,redirx)
+ tests = []
+ tests.append(glob.glob('%s/*.xml' % (docbook_output)))
+ tests.append(glob.glob('%s/*/*/*.xml' % (docbook_output)))
+ tests = ' '.join(list(itertools.chain.from_iterable(tests))).replace(self.args.outputdir +'/','').replace('\\','/')
+ exe_string = '%s --nonet --postvalid %s %s' % (self.args.xmllint,tests,redirx)
+ exe_string += ' %s more "%s/temp"' % (separ,docbook_output)
+
+ failed_docbook=False
+ xmllint_out = os.popen(exe_string).read()
+ xmllint_out = self.cleanup_xmllint_docbook(xmllint_out)
+ if xmllint_out:
+ msg += (xmllint_out,)
+ failed_docbook=True
+ elif not self.args.keep:
+ shutil.rmtree(docbook_output,ignore_errors=True)
+
if (self.args.xhtml):
html_output='%s/html' % self.test_out
if (sys.platform == 'win32'):
@@ -212,7 +282,7 @@ class Tester:
elif not self.args.keep:
shutil.rmtree(latex_output,ignore_errors=True)
- if failed_xml or failed_html or failed_latex:
+ if failed_xml or failed_html or failed_latex or failed_docbook or failed_rtf:
testmgr.ok(False,self.test_name,msg)
return
@@ -280,8 +350,12 @@ def main():
parser.add_argument('--xmllint',nargs='?',default='xmllint',help=
'path/name of the xmllint executable')
parser.add_argument('--id',nargs='+',dest='ids',action='append',type=int,help=
- 'run test with number n only (the option may be specified run test with '
- 'number n only (the option may be specified')
+ 'run test with number n only (the option can be specified to run test with '
+ 'number n only (the option can be specified multiple times')
+ parser.add_argument('--start_id',dest='start_id',type=int,help=
+ 'run tests starting with number n')
+ parser.add_argument('--end_id',dest='end_id',type=int,help=
+ 'run tests ending with number n')
parser.add_argument('--all',help=
'can be used in combination with -updateref to update the reference files '
'for all tests.',action="store_true")
@@ -293,10 +367,16 @@ def main():
'disable redirection of doxygen warnings',action="store_true")
parser.add_argument('--xml',help='create xml output and check',
action="store_true")
+ parser.add_argument('--rtf',help=
+ 'create rtf output',action="store_true")
+ parser.add_argument('--docbook',help=
+ 'create docbook output and check with xmllint',action="store_true")
parser.add_argument('--xhtml',help=
'create xhtml output and check with xmllint',action="store_true")
parser.add_argument('--pdf',help='create LaTeX output and create pdf from it',
action="store_true")
+ parser.add_argument('--subdirs',help='use the configuration parameter CREATE_SUBDIRS=YES',
+ action="store_true")
parser.add_argument('--keep',help='keep result directories',
action="store_true")
parser.add_argument('--cfg',nargs='+',dest='cfgs',action='append',help=
@@ -306,7 +386,7 @@ def main():
args = parser.parse_args(test_flags + sys.argv[1:])
# sanity check
- if (not args.xml) and (not args.pdf) and (not args.xhtml):
+ if (not args.xml) and (not args.pdf) and (not args.xhtml) and (not args.docbook and (not args.rtf)):
args.xml=True
if (not args.updateref is None) and (args.ids is None) and (args.all is None):
parser.error('--updateref requires either --id or --all')
@@ -314,15 +394,26 @@ def main():
starting_directory = os.getcwd()
os.chdir(args.inputdir)
# find the tests to run
- if args.ids: # test ids are given by user
- tests = []
+ tests = []
+ if args.start_id:
+ if args.end_id:
+ for id in range(args.start_id, args.end_id + 1):
+ tests.append(glob.glob('%s_*'%id))
+ tests.append(glob.glob('0%s_*'%id))
+ tests.append(glob.glob('00%s_*'%id))
+ else:
+ parser.error('--start_id requires --end_id')
+ elif args.end_id:
+ parser.error('--end_id requires --start_id')
+ if args.ids: # test ids are given by user
for id in list(itertools.chain.from_iterable(args.ids)):
tests.append(glob.glob('%s_*'%id))
tests.append(glob.glob('0%s_*'%id))
tests.append(glob.glob('00%s_*'%id))
- tests = list(itertools.chain.from_iterable(tests))
- else: # find all tests
+ if (not args.ids and not args.start_id): # find all tests
tests = glob.glob('[0-9][0-9][0-9]_*')
+ else:
+ tests = list(itertools.chain.from_iterable(tests))
os.chdir(starting_directory)
# create test manager to run the tests