[geany/geany] 3fda69: Merge pull request #890 from kugel-/gtkdoc-hdr

Colomban Wendling git-noreply at xxxxx
Tue Mar 1 17:53:08 UTC 2016


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Tue, 01 Mar 2016 17:53:08 UTC
Commit:      3fda6988b3b5b00dba25999de2cdb1540154701e
             https://github.com/geany/geany/commit/3fda6988b3b5b00dba25999de2cdb1540154701e

Log Message:
-----------
Merge pull request #890 from kugel-/gtkdoc-hdr

Generated and ship a GtkDoc header suitable for GObject Introspection.


Modified Paths:
--------------
    .gitignore
    .travis.yml
    Makefile.am
    configure.ac
    doc/Doxyfile.in
    doc/Makefile.am
    doc/pluginsymbols.c
    m4/geany-gtkdoc-header.m4
    scripts/gen-api-gtkdoc.py
    src/build.c
    src/dialogs.c
    src/document.c
    src/editor.c
    src/editor.h
    src/encodings.c
    src/filetypes.c
    src/filetypes.h
    src/keybindings.c
    src/plugindata.h
    src/pluginutils.c
    src/project.h
    src/search.h
    src/spawn.c
    src/stash.c
    src/ui_utils.c
    src/utils.c
    tagmanager/src/tm_workspace.c

Modified: .gitignore
3 lines changed, 3 insertions(+), 0 deletions(-)
===================================================================
@@ -99,6 +99,7 @@ Makefile.in
 # /doc/
 #-----------------------------------------------------------------------
 /doc/Doxyfile
+/doc/Doxyfile-gi
 /doc/Doxyfile.stamp
 /doc/geany.1
 /doc/geany.html
@@ -110,6 +111,8 @@ Makefile.in
 /doc/*.tex
 /doc/*.toc
 /doc/reference
+/doc/geany-gtkdoc.h
+/doc/xml/
 
 #-----------------------------------------------------------------------
 # /tests/


Modified: .travis.yml
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -16,6 +16,7 @@ install:
   - sudo apt-get install -y python-docutils rst2pdf
   # try not to install doxygen-latex because we don't need it and it's huge
   - sudo apt-get install -y --no-install-recommends doxygen
+  - sudo apt-get install -y python-lxml
 before_script:
   - export CFLAGS="-g -O2 -Werror=pointer-arith -Werror=aggregate-return -Werror=implicit-function-declaration"
 script:


Modified: Makefile.am
4 lines changed, 3 insertions(+), 1 deletions(-)
===================================================================
@@ -5,7 +5,8 @@ SUBDIRS = tagmanager scintilla src plugins icons po doc data tests
 AUTOMAKE_OPTIONS =	1.7
 
 ACLOCAL_AMFLAGS = -I m4
-AM_DISTCHECK_CONFIGURE_FLAGS = --enable-api-docs --enable-html-docs --enable-pdf-docs
+AM_DISTCHECK_CONFIGURE_FLAGS = --enable-api-docs --enable-html-docs --enable-pdf-docs \
+                               --enable-gtkdoc-header
 
 WIN32_BUILD_FILES = \
 	geany_private.rc \
@@ -15,6 +16,7 @@ WIN32_BUILD_FILES = \
 
 EXTRA_DIST = \
 	autogen.sh \
+	scripts/gen-api-gtkdoc.py \
 	wscript \
 	waf \
 	geany.desktop.in \


Modified: configure.ac
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -123,6 +123,7 @@ AC_SUBST([pkgdatadir])
 # Documentation tools
 GEANY_CHECK_DOCUTILS
 GEANY_CHECK_DOXYGEN
+GEANY_CHECK_GTKDOC_HEADER
 
 # libgeany
 GEANY_LIB_INIT


Modified: doc/Doxyfile.in
22 lines changed, 20 insertions(+), 2 deletions(-)
===================================================================
@@ -247,7 +247,22 @@ ALIASES                = "signal=- @ref  " \
                          "endsignalproto=@endcode  " \
                          "signaldesc=" \
                          "signals=@b Signals:  " \
-                         "endsignals=  "
+                         "endsignals=  " \
+                         "gironly=@internal"
+
+# Apparently Doxygen doesn't seem to like \<type>only without a previous command, so create a no-op
+ALIASES               += "noop=\if FALSE \endif"
+ALIASES               += "transfer{1}=\noop \xmlonly <simplesect kind=\"geany:transfer\">\1</simplesect>\endxmlonly \htmlonly <em title=\"Ownership transfer to the caller: \1\">(transfer: \1)</em> \endhtmlonly"
+ALIASES               += "elementtype{1}=\noop \xmlonly <simplesect kind=\"geany:element-type\">\1</simplesect>\endxmlonly \htmlonly <em title=\"Type of the elements in the container: \1\">(element-type: \1)</em> \endhtmlonly"
+ALIASES               += "scope{1}=\noop \xmlonly <simplesect kind=\"geany:scope\">\1</simplesect>\endxmlonly \htmlonly <em>(scope: \1)</em> \endhtmlonly"
+ALIASES               += "girskip=\noop \xmlonly <simplesect kind=\"geany:skip\"></simplesect>\endxmlonly"
+ALIASES               += "nullable=\noop \xmlonly <simplesect kind=\"geany:nullable\"></simplesect>\endxmlonly"
+ALIASES               += "out=\noop \xmlonly <simplesect kind=\"geany:out\"></simplesect>\endxmlonly \htmlonly <em title=\"Output parameter\">(out)</em> \endhtmlonly"
+ALIASES               += "optional=\noop \xmlonly <simplesect kind=\"geany:optional\"></simplesect>\endxmlonly"
+ALIASES               += "cb=\noop \xmlonly <simplesect kind=\"geany:scope\">notified</simplesect>\endxmlonly"
+ALIASES               += "cbdata=\noop \xmlonly <simplesect kind=\"geany:closure\"></simplesect>\endxmlonly"
+ALIASES               += "cbfree=\noop \xmlonly <simplesect kind=\"geany:destroy\"></simplesect>\endxmlonly"
+
 
 # This tag can be used to specify a number of word-keyword mappings (TCL only).
 # A mapping has the form "name=value". For example adding "class=itcl::class"
@@ -834,7 +849,7 @@ RECURSIVE              = NO
 # Note that relative paths are relative to the directory from which doxygen is
 # run.
 
-EXCLUDE                =
+EXCLUDE                = @top_srcdir@/doc/geany-gtkdoc.h
 
 # The 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
@@ -2020,7 +2035,10 @@ INCLUDE_FILE_PATTERNS  =
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 PREDEFINED             = "G_GNUC_PRINTF(x,y)=" \
+                         G_BEGIN_DECLS= \
+                         G_END_DECLS= \
                          HAVE_PLUGINS \
+                         GEANY_API_SYMBOL= \
                          GEANY_FUNCTIONS_H
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this


Modified: doc/Makefile.am
41 lines changed, 39 insertions(+), 2 deletions(-)
===================================================================
@@ -102,12 +102,49 @@ doxygen_sources = \
 Doxyfile.stamp: Doxyfile $(doxygen_sources)
 	$(AM_V_GEN)$(DOXYGEN) Doxyfile && echo "" > $@
 
-all-local: Doxyfile.stamp
+ALL_LOCAL_TARGETS = Doxyfile.stamp
+CLEAN_LOCAL_TARGETS = clean-api-docs-local
 
-clean-local: clean-api-docs-local
 clean-api-docs-local:
 	-rm -rf reference/ Doxyfile.stamp doxygen_*
 
+if ENABLE_GTKDOC_HEADER
+
+# set WARN_IF_UNDOCUMENTED because apparently doxygens warns for undocumented stuff
+# in headers (even though it's correctly documented in the corresponding .c file) only
+# for xml output
+Doxyfile-gi: Doxyfile
+	$(AM_V_GEN)$(SED) \
+		-e 's,gironly=@internal,gironly=,' \
+		-e 's,^\(GENERATE_HTML.*\)YES,\1NO,' \
+		-e 's,^\(GENERATE_XML.*\)NO,\1YES,' \
+		-e 's,^\(WARN_IF_UNDOCUMENTED.*\)YES,\1NO,' \
+		-e 's,^\(SORT_MEMBER_DOCS.*\)YES,\1NO,' \
+		-e 's,^\(SORT_BRIEF_DOCS.*\)YES,\1NO,' \
+		$< > $@ || { $(RM) $@ && exit 1; }
+
+# we depend on Doxyfile.stamp not have this run in parallel with it to avoid
+# concurrent Doxygen runs, which might overwrite each other's files
+Doxyfile-gi.stamp: Doxyfile-gi Doxyfile.stamp $(doxygen_sources)
+	$(AM_V_GEN)$(DOXYGEN) Doxyfile-gi && echo "" > $@
+
+geany-gtkdoc.h: Doxyfile-gi.stamp $(top_srcdir)/scripts/gen-api-gtkdoc.py
+	$(AM_V_GEN)$(top_srcdir)/scripts/gen-api-gtkdoc.py xml -d $(builddir) -o $@
+
+geany_gtkdocincludedir = $(includedir)/geany/gtkdoc
+nodist_geany_gtkdocinclude_HEADERS = geany-gtkdoc.h
+
+ALL_LOCAL_TARGETS += geany-gtkdoc.h
+CLEAN_LOCAL_TARGETS += clean-gtkdoc-header-local
+
+clean-gtkdoc-header-local:
+	-rm -rf xml/ Doxyfile-gi Doxyfile-gi.stamp geany-gtkdoc.h
+
+endif
+
+all-local: $(ALL_LOCAL_TARGETS)
+clean-local: $(CLEAN_LOCAL_TARGETS)
+
 endif
 
 uninstall-local:


Modified: doc/pluginsymbols.c
4 lines changed, 3 insertions(+), 1 deletions(-)
===================================================================
@@ -87,7 +87,9 @@ KeyBindingGroup *plugin_key_group;
  * @param dialog The plugin preferences dialog widget - this should only be used to
  * connect the @c "response" signal. If settings should be read from the dialog, the
  * response will be either @c GTK_RESPONSE_OK or @c GTK_RESPONSE_APPLY.
- * @return A container widget holding preference widgets.
+ *
+ * @return @transfer{floating} A container widget holding preference widgets.
+ *
  * @note Using @link stash.h Stash @endlink can make implementing preferences easier.
  * @see plugin_configure_single(). */
 GtkWidget *plugin_configure(GtkDialog *dialog);


Modified: m4/geany-gtkdoc-header.m4
42 lines changed, 42 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,42 @@
+AC_DEFUN([_GEANY_CHECK_GTKDOC_HEADER_ERROR],
+[
+	AC_MSG_ERROR([GtkDoc header generation enabled but $1])
+])
+
+dnl GEANY_CHECK_GTKDOC_HEADER
+dnl checks for GtkDoc header generation requirements and define
+dnl ENABLE_GTKDOC_HEADER Automake conditional as appropriate
+AC_DEFUN([GEANY_CHECK_GTKDOC_HEADER],
+[
+	AC_REQUIRE([GEANY_CHECK_DOXYGEN])
+
+	AC_ARG_ENABLE([gtkdoc-header],
+			[AS_HELP_STRING([--enable-gtkdoc-header],
+					[generate the GtkDoc header suitable for GObject introspection [default=auto]])],
+			[geany_enable_gtkdoc_header="$enableval"],
+			[geany_enable_gtkdoc_header="auto"])
+
+	AS_IF([test "x$geany_enable_gtkdoc_header$geany_with_doxygen" = "xyesno"],
+	      [_GEANY_CHECK_GTKDOC_HEADER_ERROR([Doxygen support not available])],
+	      [test "x$geany_enable_gtkdoc_header" != "xno"],
+	[
+		dnl python
+		AM_PATH_PYTHON([2.7], [have_python=yes], [have_python=no])
+		dnl lxml module
+		AS_IF([test "x$have_python" = xyes],
+		      [have_python_and_lxml=yes
+		       AC_MSG_CHECKING([for python lxml package])
+		       AS_IF([$PYTHON -c 'import lxml' 2>&1 >/dev/null],
+		             [have_python_and_lxml=yes],
+		             [have_python_and_lxml=no])
+		       AC_MSG_RESULT([$have_python_and_lxml])],
+		      [have_python_and_lxml=no])
+		dnl final result
+		AS_IF([test "x$geany_enable_gtkdoc_header$have_python_and_lxml" = "xyesno"],
+		      [_GEANY_CHECK_GTKDOC_HEADER_ERROR([python or its lxml module not found])],
+		      [geany_enable_gtkdoc_header=yes])
+	])
+
+	AM_CONDITIONAL([ENABLE_GTKDOC_HEADER], [test "x$geany_enable_gtkdoc_header" = "xyes"])
+	GEANY_STATUS_ADD([Generate GtkDoc header], [$geany_enable_gtkdoc_header])
+])


Modified: scripts/gen-api-gtkdoc.py
425 lines changed, 425 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,425 @@
+#!/usr/bin/env python
+#
+#  Copyright 2015-2016 Thomas Martitz <kugel at rockbox.org>
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+#  MA 02110-1301, USA.
+
+import os
+import sys
+import re
+from lxml import etree
+from optparse import OptionParser
+
+
+def normalize_text(s):
+    r"""
+    Normalizes whitespace in text.
+
+    >>> normalize_text("asd xxx")
+    'asd xxx'
+    >>> normalize_text(" asd\nxxx  ")
+    'asd xxx'
+    """
+    return s.replace("\n", " ").strip()
+
+
+CXX_NAMESPACE_RE = re.compile(r'[_a-zA-Z][_0-9a-zA-Z]*::')
+def fix_definition(s):
+    """
+    Removes C++ name qualifications from some definitions.
+
+    For example:
+
+    >>> fix_definition("bool flag")
+    'bool flag'
+    >>> fix_definition("bool FooBar::flag")
+    'bool flag'
+    >>> fix_definition("void(* _GeanyObjectClass::project_open) (GKeyFile *keyfile)")
+    'void(* project_open) (GKeyFile *keyfile)'
+
+    """
+    return CXX_NAMESPACE_RE.sub(r"", s)
+
+
+class AtDoc(object):
+    def __init__(self):
+        self.retval = None
+        self.since = ""
+        self.annot = []
+
+    def cb(self, type, str):
+        if (type == "param"):
+            words = str.split(" ", 2)
+            self.annot = []
+        elif (type == "return"):
+            self.annot = []
+        elif (type == "since"):
+            self.since = str.rstrip()
+        elif type in ("geany:nullable",
+                      "geany:optional",
+                      "geany:out",
+                      "geany:skip",
+                      "geany:closure",
+                      "geany:destroy"):
+            self.annot.append(type.split(":")[1])
+        elif type in ("geany:transfer",
+                      "geany:element-type",
+                      "geany:scope"):
+            type = type.split(":")[1]
+            self.annot.append("%s %s" % (type, str))
+        elif (type == "see"):
+            return "See " + str
+        elif type in ("a", "c") and str in ("NULL", "TRUE", "FALSE"):
+            # FIXME: some of Geany does @a NULL instead of @c NULL
+            return "%" + str
+        elif (type == "a"):
+            return "@" + str
+        else:
+            return str
+
+        return ""
+
+
+class DoxygenProcess(object):
+    def __init__(self):
+        self.at = None
+
+    # http://stackoverflow.com/questions/4624062/get-all-text-inside-a-tag-in-lxml
+    @staticmethod
+    def stringify_children(node):
+        from lxml.etree import tostring
+        from itertools import chain
+        parts = ([node.text] +
+                 list(chain(*([c.text, tostring(c).decode("utf-8"), c.tail] for c in node.getchildren()))) +
+                 [node.tail])
+        # filter removes possible Nones in texts and tails
+        return "".join(filter(None, parts))
+
+    def get_program_listing(self, xml):
+        from lxml.etree import tostring
+        arr = ["", "|[<!-- language=\"C\" -->"]
+        for l in xml.getchildren():
+            if (l.tag == "codeline"):
+                # a codeline is of the form
+                # <highlight class="normal">GeanyDocument<sp/>*doc<sp/>=<sp/>...;</highlight>
+                # <sp/> tags must be replaced with spaces, then just use the text
+                h = l.find("highlight")
+                if h is not None:
+                    html = tostring(h).decode("utf-8")
+                    html = html.replace("<sp/>", " ")
+                    arr.append("  " + tostring(etree.HTML(html), method="text").decode("utf-8"))
+        arr.append("]|")
+        return "\n".join(arr)
+
+    def join_annot(self):
+        s = " ".join(map(lambda x: "(%s)" % x, self.at.annot))
+        return s + ": " if s else ""
+
+    def process_element(self, xml):
+        self.at = AtDoc()
+        s = self.__process_element(xml)
+        return s
+
+    def get_extra(self):
+        return self.join_annot()
+
+    def get_return(self):
+        return self.at.retval
+
+    def get_since(self):
+        return self.at.since
+
+    def __process_element(self, xml):
+        s = ""
+
+        if xml.text:
+            s += xml.text
+        for n in xml.getchildren():
+            if n.tag == "emphasis":
+                s += self.at.cb("a", self.__process_element(n))
+            if n.tag == "computeroutput":
+                s += self.at.cb("c", self.__process_element(n))
+            if n.tag == "itemizedlist":
+                s += "\n" + self.__process_element(n)
+            if n.tag == "listitem":
+                s += " - " + self.__process_element(n)
+            if n.tag == "para":
+                s += self.__process_element(n) + "\n"
+            if n.tag == "ref":
+                s += n.text if n.text else ""
+            if n.tag == "simplesect":
+                ss = self.at.cb(n.get("kind"), self.__process_element(n))
+                s += ss + "\n" if ss else ""
+            if n.tag == "programlisting":
+                s += self.get_program_listing(n)
+            if n.tag == "xrefsect":
+                s += self.__process_element(n)
+            if n.tag == "xreftitle":
+                s += self.__process_element(n) + ": "
+            if n.tag == "xrefdescription":
+                s += self.__process_element(n)
+            if n.tag == "ulink":
+                s += self.__process_element(n)
+            if n.tag == "linebreak":
+                s += "\n"
+            if n.tag == "ndash":
+                s += "--"
+                # workaround for doxygen bug #646002
+            if n.tag == "htmlonly":
+                s += ""
+            if n.tail:
+                s += n.tail
+            if n.tag.startswith("param"):
+                pass  # parameters are handled separately in DoxyFunction::from_memberdef()
+        return s
+
+
+class DoxyMember(object):
+    def __init__(self, name, brief, extra=""):
+        self.name       = name
+        self.brief      = brief
+        self.extra      = extra
+
+
+class DoxyElement(object):
+
+    def __init__(self, name, definition, **kwargs):
+        self.name       = name
+        self.definition = definition
+        self.brief      = kwargs.get('brief', "")
+        self.detail     = kwargs.get('detail', "")
+        self.members    = kwargs.get('members', [])
+        self.since      = kwargs.get('since', "")
+        self.extra      = kwargs.get('extra', "")
+        self.retval     = kwargs.get('retval', None)
+
+    def is_documented(self):
+        if (normalize_text(self.brief)) != "":
+            return True
+        return False
+
+    def add_brief(self, xml):
+        proc = DoxygenProcess()
+        self.brief = proc.process_element(xml)
+        self.extra += proc.get_extra()
+
+    def add_detail(self, xml):
+        proc = DoxygenProcess()
+        self.detail = proc.process_element(xml)
+        self.extra += proc.get_extra()
+        self.since = proc.get_since()
+
+    def add_member(self, xml):
+        name = xml.find("name").text
+        proc = DoxygenProcess()
+        brief = proc.process_element(xml.find("briefdescription"))
+        # optional doxygen command output appears within <detaileddescription />
+        proc.process_element(xml.find("detaileddescription"))
+        self.members.append(DoxyMember(name, normalize_text(brief), proc.get_extra()))
+
+    def add_param(self, xml):
+        name = xml.find("parameternamelist").find("parametername").text
+        proc = DoxygenProcess()
+        brief = proc.process_element(xml.find("parameterdescription"))
+        self.members.append(DoxyMember(name, normalize_text(brief), proc.get_extra()))
+
+    def add_return(self, xml):
+        proc = DoxygenProcess()
+        brief = proc.process_element(xml)
+        self.retval = DoxyMember("ret", normalize_text(brief), proc.get_extra())
+
+    def to_gtkdoc(self):
+        s = []
+        s.append("/**")
+        s.append(" * %s: %s" % (self.name, self.extra))
+        for p in self.members:
+            s.append(" * @%s: %s %s" % (p.name, p.extra, p.brief))
+        s.append(" *")
+        s.append(" * %s" % self.brief.replace("\n", "\n * "))
+        s.append(" *")
+        s.append(" * %s" % self.detail.replace("\n", "\n * "))
+        s.append(" *")
+        if self.retval:
+            s.append(" * Returns: %s %s" % (self.retval.extra, self.retval.brief))
+        if self.since:
+            s.append(" *")
+            s.append(" * Since: %s" % self.since)
+        s.append(" */")
+        s.append("")
+        return "\n".join(s)
+
+
+class DoxyTypedef(DoxyElement):
+    @staticmethod
+    def from_memberdef(xml):
+        name = xml.find("name").text
+        d = normalize_text(xml.find("definition").text)
+        d += ";"
+        return DoxyTypedef(name, d)
+
+
+class DoxyEnum(DoxyElement):
+    @staticmethod
+    def from_memberdef(xml):
+        name = xml.find("name").text
+        d = "typedef enum {\n"
+        for member in xml.findall("enumvalue"):
+            v = member.find("initializer")
+            d += "\t%s%s,\n" % (member.find("name").text, " "+v.text if v is not None else "")
+        d += "} %s;\n" % name
+
+        e = DoxyEnum(name, d)
+        e.add_brief(xml.find("briefdescription"))
+        for p in xml.findall("enumvalue"):
+            e.add_member(p)
+        return e
+
+
+class DoxyStruct(DoxyElement):
+    @staticmethod
+    def from_compounddef(xml, typedefs=[]):
+        name = xml.find("compoundname").text
+        section = xml.find("sectiondef")
+        d = "struct %s {\n" % name
+        for p in section.findall("memberdef"):
+            # workaround for struct members. g-ir-scanner can't properly map struct members
+            # (beginning with struct GeanyFoo) to the typedef and assigns a generic type for them
+            # thus we fix that up here and enforce usage of the typedef. These are written
+            # out first, before any struct definition, for this reason
+            # Exception: there are no typedefs for GeanyFooPrivate so skip those. Their exact
+            # type isn't needed anyway
+            s = fix_definition(p.find("definition").text).lstrip()
+            proc = DoxygenProcess()
+            brief = proc.process_element(p.find("briefdescription"))
+            private = (normalize_text(brief) == "")
+            words = s.split()
+            if (words[0] == "struct"):
+                if not (words[1].endswith("Private") or words[1].endswith("Private*")):
+                    s = " ".join(words[1:])
+            d += "\t/*< %s >*/\n\t%s;\n" % ("private" if private else "public", s)
+
+        d += "};\n"
+        e = DoxyStruct(name, d)
+        e.add_brief(xml.find("briefdescription"))
+        for p in section.findall("memberdef"):
+            e.add_member(p)
+        return e
+
+
+class DoxyFunction(DoxyElement):
+    @staticmethod
+    def from_memberdef(xml):
+        name = xml.find("name").text
+        d = normalize_text(xml.find("definition").text)
+        d += " " + xml.find("argsstring").text + ";"
+        d = normalize_text(d)
+
+        e = DoxyFunction(name, d)
+        e.add_brief(xml.find("briefdescription"))
+        e.add_detail(xml.find("detaileddescription"))
+        for p in xml.xpath(".//detaileddescription/*/parameterlist[@kind='param']/parameteritem"):
+            e.add_param(p)
+        x = xml.xpath(".//detaileddescription/*/simplesect[@kind='return']")
+        if (len(x) > 0):
+            e.add_return(x[0])
+        return e
+
+
+def main(args):
+    xml_dir = None
+    outfile = None
+
+    parser = OptionParser(usage="usage: %prog [options] XML_DIR")
+    parser.add_option("--xmldir", metavar="DIRECTORY", help="Path to Doxygen-generated XML files",
+                      action="store", dest="xml_dir")
+    parser.add_option("-d", "--outdir", metavar="DIRECTORY", help="Path to Doxygen-generated XML files",
+                      action="store", dest="outdir", default=".")
+    parser.add_option("-o", "--output", metavar="FILE", help="Write output to FILE",
+                      action="store", dest="outfile")
+    opts, args = parser.parse_args(args[1:])
+
+    xml_dir = args[0]
+
+    if not (os.path.exists(xml_dir)):
+        sys.stderr.write("invalid xml directory\n")
+        return 1
+
+    transform = etree.XSLT(etree.parse(os.path.join(xml_dir, "combine.xslt")))
+    doc = etree.parse(os.path.join(xml_dir, "index.xml"))
+    root = transform(doc)
+
+    other = []
+    typedefs = []
+
+    c_files = root.xpath(".//compounddef[@kind='file']/compoundname[substring(.,string-length(.)-1)='.c']/..")
+    h_files = root.xpath(".//compounddef[@kind='file']/compoundname[substring(.,string-length(.)-1)='.h']/..")
+
+    for f in h_files:
+        if not (f.find("compoundname").text.endswith("private.h")):
+            for n0 in f.xpath(".//*/memberdef[@kind='typedef' and @prot='public']"):
+                if not (n0.find("type").text.startswith("enum")):
+                    e = DoxyTypedef.from_memberdef(n0)
+                    typedefs.append(e)
+
+        for n0 in f.xpath(".//*/memberdef[@kind='enum' and @prot='public']"):
+            e = DoxyEnum.from_memberdef(n0)
+            other.append(e)
+
+    for n0 in root.xpath(".//compounddef[@kind='struct' and @prot='public']"):
+        e = DoxyStruct.from_compounddef(n0)
+        other.append(e)
+
+    for f in c_files:
+        for n0 in f.xpath(".//*/memberdef[@kind='function' and @prot='public']"):
+            e = DoxyFunction.from_memberdef(n0)
+            other.append(e)
+
+    if (opts.outfile):
+        try:
+            outfile = open(opts.outfile, "w+")
+        except OSError as err:
+            sys.stderr.write("failed to open \"%s\" for writing (%s)\n" % (opts.outfile, err.strerror))
+            return 1
+    else:
+        outfile = sys.stdout
+
+    try:
+        outfile.write("/*\n * Automatically generated file - do not edit\n */\n\n")
+        outfile.write("#include <glib.h>\n")
+        outfile.write("#include <gtk/gtk.h>\n\n")
+        outfile.write("typedef struct _ScintillaObject ScintillaObject;\n")
+        outfile.write("typedef struct TMSourceFile TMSourceFile;\n")
+        outfile.write("typedef struct TMWorkspace TMWorkspace;\n")
+
+        # write typedefs first, they are possibly undocumented but still required (even
+        # if they are documented, they must be written out without gtkdoc)
+        for e in typedefs:
+            outfile.write(e.definition)
+            outfile.write("\n\n")
+
+        for e in filter(lambda x: x.is_documented(), other):
+            outfile.write("\n\n")
+            outfile.write(e.to_gtkdoc())
+            outfile.write(e.definition)
+            outfile.write("\n\n")
+    except BrokenPipeError:
+        # probably piped to head or tail
+        return 0
+
+    return 0
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv))


Modified: src/build.c
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -553,7 +553,7 @@ GeanyBuildCommand *build_get_menu_item(GeanyBuildSource src, GeanyBuildGroup grp
  * @param cmd the index of the command within the group.
  * @param fld the field to return
  *
- * @return a pointer to the constant string or @c NULL if it doesn't exist.
+ * @return @nullable a pointer to the constant string or @c NULL if it doesn't exist.
  *         This is a pointer to an internal structure and must not be freed.
  *
  **/


Modified: src/dialogs.c
8 lines changed, 4 insertions(+), 4 deletions(-)
===================================================================
@@ -1058,11 +1058,11 @@ static void on_dialog_input(const gchar *str, gpointer data)
 
 /** Asks the user for text input.
  * @param title Dialog title.
- * @param parent The currently focused window, usually @c geany->main_widgets->window.
+ * @param parent @nullable The currently focused window, usually @c geany->main_widgets->window.
  * 	@c NULL can be used but is discouraged due to window manager effects.
- * @param label_text Label text, or @c NULL.
- * @param default_text Text to display in the input field, or @c NULL.
- * @return New copy of user input or @c NULL if cancelled.
+ * @param label_text @nullable Label text, or @c NULL.
+ * @param default_text @nullable Text to display in the input field, or @c NULL.
+ * @return @nullable New copy of user input or @c NULL if cancelled.
  * @since 0.20. */
 GEANY_API_SYMBOL
 gchar *dialogs_show_input(const gchar *title, GtkWindow *parent, const gchar *label_text,


Modified: src/document.c
40 lines changed, 20 insertions(+), 20 deletions(-)
===================================================================
@@ -146,7 +146,7 @@ static GtkWidget* document_show_message(GeanyDocument *doc, GtkMessageType msgty
  * @param realname The filename to search, which should be identical to the
  * string returned by @c tm_get_real_path().
  *
- * @return The matching document, or @c NULL.
+ * @return @transfer{none} @nullable The matching document, or @c NULL.
  * @note This is only really useful when passing a @c TMSourceFile::file_name.
  * @see GeanyDocument::real_path.
  * @see document_find_by_filename().
@@ -196,7 +196,7 @@ static gchar *get_real_path_from_utf8(const gchar *utf8_filename)
  *
  *  @param utf8_filename The filename to search (in UTF-8 encoding).
  *
- *  @return The matching document, or @c NULL.
+ *  @return @transfer{none} @nullable The matching document, or @c NULL.
  *  @see document_find_by_real_path().
  **/
 GEANY_API_SYMBOL
@@ -250,7 +250,7 @@ GeanyDocument *document_find_by_sci(ScintillaObject *sci)
  * Useful when the corresponding document may have been closed since the
  * ID was retrieved.
  * @param id The ID of the document to find
- * @return @c NULL if the document is no longer open.
+ * @return @transfer{none} @c NULL if the document is no longer open.
  *
  * Example:
  * @code
@@ -366,7 +366,7 @@ GeanyDocument *document_get_from_notebook_child(GtkWidget *page)
  *
  *  @param page_num The notebook page number to search.
  *
- *  @return The corresponding document for the given notebook page, or @c NULL.
+ *  @return @transfer{none} @nullable The corresponding document for the given notebook page, or @c NULL.
  **/
 GEANY_API_SYMBOL
 GeanyDocument *document_get_from_page(guint page_num)
@@ -385,7 +385,7 @@ GeanyDocument *document_get_from_page(guint page_num)
 /**
  *  Finds the current document.
  *
- *  @return A pointer to the current document or @c NULL if there are no opened documents.
+ *  @return @transfer{none} @nullable A pointer to the current document or @c NULL if there are no opened documents.
  **/
 GEANY_API_SYMBOL
 GeanyDocument *document_get_current(void)
@@ -830,11 +830,11 @@ GeanyDocument *document_new_file_if_non_open(void)
  *  Line endings in @a text will be converted to the default setting.
  *  Afterwards, the @c "document-new" signal is emitted for plugins.
  *
- *  @param utf8_filename The file name in UTF-8 encoding, or @c NULL to open a file as "untitled".
- *  @param ft The filetype to set or @c NULL to detect it from @a filename if not @c NULL.
- *  @param text The initial content of the file (in UTF-8 encoding), or @c NULL.
+ *  @param utf8_filename @nullable The file name in UTF-8 encoding, or @c NULL to open a file as "untitled".
+ *  @param ft @nullable The filetype to set or @c NULL to detect it from @a filename if not @c NULL.
+ *  @param text @nullable The initial content of the file (in UTF-8 encoding), or @c NULL.
  *
- *  @return The new document.
+ *  @return @transfer{none} The new document.
  **/
 GEANY_API_SYMBOL
 GeanyDocument *document_new_file(const gchar *utf8_filename, GeanyFiletype *ft, const gchar *text)
@@ -915,10 +915,10 @@ GeanyDocument *document_new_file(const gchar *utf8_filename, GeanyFiletype *ft,
  *
  *  @param locale_filename The filename of the document to load, in locale encoding.
  *  @param readonly Whether to open the document in read-only mode.
- *  @param ft The filetype for the document or @c NULL to auto-detect the filetype.
- *  @param forced_enc The file encoding to use or @c NULL to auto-detect the file encoding.
+ *  @param ft @nullable The filetype for the document or @c NULL to auto-detect the filetype.
+ *  @param forced_enc @nullable The file encoding to use or @c NULL to auto-detect the file encoding.
  *
- *  @return The document opened or @c NULL.
+ *  @return @transfer{none} @nullable The document opened or @c NULL.
  **/
 GEANY_API_SYMBOL
 GeanyDocument *document_open_file(const gchar *locale_filename, gboolean readonly,
@@ -1562,10 +1562,10 @@ void document_open_file_list(const gchar *data, gsize length)
  *  Opens each file in the list @a filenames.
  *  Internally, document_open_file() is called for every list item.
  *
- *  @param filenames A list of filenames to load, in locale encoding.
+ *  @param filenames @elementtype{filename} A list of filenames to load, in locale encoding.
  *  @param readonly Whether to open the document in read-only mode.
- *  @param ft The filetype for the document or @c NULL to auto-detect the filetype.
- *  @param forced_enc The file encoding to use or @c NULL to auto-detect the file encoding.
+ *  @param ft @nullable The filetype for the document or @c NULL to auto-detect the filetype.
+ *  @param forced_enc @nullable The file encoding to use or @c NULL to auto-detect the file encoding.
  **/
 GEANY_API_SYMBOL
 void document_open_files(const GSList *filenames, gboolean readonly, GeanyFiletype *ft,
@@ -1603,7 +1603,7 @@ static void on_keep_edit_history_on_reload_response(GtkWidget *bar, gint respons
  *  @a forced_enc or @c NULL to auto-detect the file encoding.
  *
  *  @param doc The document to reload.
- *  @param forced_enc The file encoding to use or @c NULL to auto-detect the file encoding.
+ *  @param forced_enc @nullable The file encoding to use or @c NULL to auto-detect the file encoding.
  *
  *  @return @c TRUE if the document was actually reloaded or @c FALSE otherwise.
  **/
@@ -1816,7 +1816,7 @@ gboolean document_need_save_as(GeanyDocument *doc)
  * Saves the document, detecting the filetype.
  *
  * @param doc The document for the file to save.
- * @param utf8_fname The new name for the document, in UTF-8, or NULL.
+ * @param utf8_fname @nullable The new name for the document, in UTF-8, or @c NULL.
  * @return @c TRUE if the file was saved or @c FALSE if the file could not be saved.
  *
  * @see document_save_file().
@@ -3241,8 +3241,8 @@ const gchar *document_get_status_widget_class(GeanyDocument *doc)
  *
  *  @param doc The document to use.
  *
- *  @return The color for the document or @c NULL if the default color should be used. The color
- *          object is owned by Geany and should not be modified or freed.
+ *  @return @nullable The color for the document or @c NULL if the default color should be used.
+ *          The color object is owned by Geany and should not be modified or freed.
  *
  *  @since 0.16
  */
@@ -3294,7 +3294,7 @@ const GdkColor *document_get_status_color(GeanyDocument *doc)
 /** Accessor function for @ref documents_array items.
  * @warning Always check the returned document is valid (@c doc->is_valid).
  * @param idx @c documents_array index.
- * @return The document, or @c NULL if @a idx is out of range.
+ * @return @transfer{none} @nullable The document, or @c NULL if @a idx is out of range.
  *
  *  @since 0.16
  */


Modified: src/editor.c
18 lines changed, 9 insertions(+), 9 deletions(-)
===================================================================
@@ -1259,7 +1259,7 @@ get_default_indent_prefs(void)
  * Prefs can be different according to project or document.
  * @warning Always get a fresh result instead of keeping a pointer to it if the editor/project
  * settings may have changed, or if this function has been called for a different editor.
- * @param editor The editor, or @c NULL to get the default indent prefs.
+ * @param editor @nullable The editor, or @c NULL to get the default indent prefs.
  * @return The indent prefs. */
 GEANY_API_SYMBOL
 const GeanyIndentPrefs *
@@ -1781,7 +1781,7 @@ void editor_find_current_word_sciwc(GeanyEditor *editor, gint pos, gchar *word,
  *                   as part of a word. May be @c NULL to use the default wordchars,
  *                   see @ref GEANY_WORDCHARS.
  *
- *  @return A newly-allocated string containing the word at the given @a pos or @c NULL.
+ *  @return @nullable A newly-allocated string containing the word at the given @a pos or @c NULL.
  *          Should be freed when no longer needed.
  *
  *  @since 0.16
@@ -4293,7 +4293,7 @@ void editor_insert_color(GeanyEditor *editor, const gchar *colour)
  *  Retrieves the end of line characters mode (LF, CR/LF, CR) in the given editor.
  *  If @a editor is @c NULL, the default end of line characters are used.
  *
- *  @param editor The editor to operate on, or @c NULL to query the default value.
+ *  @param editor @nullable The editor to operate on, or @c NULL to query the default value.
  *  @return The used end of line characters mode.
  *
  *  @since 0.20
@@ -4315,7 +4315,7 @@ gint editor_get_eol_char_mode(GeanyEditor *editor)
  *  (LF, CR/LF, CR) in the given editor.
  *  If @a editor is @c NULL, the default end of line characters are used.
  *
- *  @param editor The editor to operate on, or @c NULL to query the default value.
+ *  @param editor @nullable The editor to operate on, or @c NULL to query the default value.
  *  @return The name of the end of line characters.
  *
  *  @since 0.19
@@ -4337,7 +4337,7 @@ const gchar *editor_get_eol_char_name(GeanyEditor *editor)
  *  If @a editor is @c NULL, the default end of line characters are used.
  *  The returned value is 1 for CR and LF and 2 for CR/LF.
  *
- *  @param editor The editor to operate on, or @c NULL to query the default value.
+ *  @param editor @nullable The editor to operate on, or @c NULL to query the default value.
  *  @return The length of the end of line characters.
  *
  *  @since 0.19
@@ -4363,7 +4363,7 @@ gint editor_get_eol_char_len(GeanyEditor *editor)
  *  If @a editor is @c NULL, the default end of line characters are used.
  *  The returned value is either "\n", "\r\n" or "\r".
  *
- *  @param editor The editor to operate on, or @c NULL to query the default value.
+ *  @param editor @nullable The editor to operate on, or @c NULL to query the default value.
  *  @return The end of line characters.
  *
  *  @since 0.19
@@ -4996,7 +4996,7 @@ static ScintillaObject *create_new_sci(GeanyEditor *editor)
 
 /** Creates a new Scintilla @c GtkWidget based on the settings for @a editor.
  * @param editor Editor settings.
- * @return The new widget.
+ * @return @transfer{floating} The new widget.
  *
  * @since 0.15
  **/
@@ -5327,9 +5327,9 @@ void editor_indent(GeanyEditor *editor, gboolean increase)
  * If @a editor is passed, returns a snippet specific to the document filetype.
  * If @a editor is @c NULL, returns a snippet from the default set.
  *
- * @param editor Editor or @c NULL.
+ * @param editor @nullable Editor or @c NULL.
  * @param snippet_name Snippet name.
- * @return snippet or @c NULL if it was not found. Must not be freed.
+ * @return @nullable snippet or @c NULL if it was not found. Must not be freed.
  */
 GEANY_API_SYMBOL
 const gchar *editor_find_snippet(GeanyEditor *editor, const gchar *snippet_name)


Modified: src/editor.h
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -50,6 +50,8 @@ typedef enum
 }
 GeanyIndentType;
 
+/** @gironly
+ * Auto indentation modes */
 typedef enum
 {
 	GEANY_AUTOINDENT_NONE = 0,


Modified: src/encodings.c
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -260,7 +260,7 @@ const GeanyEncoding *encodings_get_from_index(gint idx)
  *  @param idx @ref GeanyEncodingIndex to retrieve the corresponding character set.
  *
  *
- *  @return The charset according to idx, or @c NULL if the index is invalid.
+ *  @return @nullable The charset according to idx, or @c NULL if the index is invalid.
  *
  *  @since 0.13
  **/
@@ -775,9 +775,9 @@ static gchar *encodings_convert_to_utf8_with_suggestion(const gchar *buffer, gss
  *
  *  @param buffer the input string to convert.
  *  @param size the length of the string, or -1 if the string is nul-terminated.
- *  @param used_encoding return location of the detected encoding of the input string, or @c NULL.
+ *  @param used_encoding @out @optional return location of the detected encoding of the input string, or @c NULL.
  *
- *  @return If the conversion was successful, a newly allocated nul-terminated string,
+ *  @return @nullable If the conversion was successful, a newly allocated nul-terminated string,
  *    which must be freed with @c g_free(). Otherwise @c NULL.
  **/
 GEANY_API_SYMBOL


Modified: src/filetypes.c
19 lines changed, 13 insertions(+), 6 deletions(-)
===================================================================
@@ -55,7 +55,14 @@
 
 #define GEANY_FILETYPE_SEARCH_LINES 2 /* lines of file to search for filetype */
 
-GPtrArray *filetypes_array = NULL;	/* Dynamic array of filetype pointers */
+/** Dynamic array of filetype pointers
+ *
+ * List the list is dynamically expanded for custom filetypes filetypes so don't expect
+ * the list of known filetypes to be a constant.
+ *
+ * @elementtype{GeanyFiletype}
+ * */
+GPtrArray *filetypes_array = NULL;
 
 static GHashTable *filetypes_hash = NULL;	/* Hash of filetype pointers based on name keys */
 
@@ -233,7 +240,7 @@ static gint cmp_filetype(gconstpointer pft1, gconstpointer pft2, gpointer data)
 
 /** Gets a list of filetype pointers sorted by name.
  * The list does not change on subsequent calls.
- * @return The list - do not free.
+ * @return @elementtype{GeanyFiletype} @transfer{none} The list - do not free.
  * @see filetypes_by_title. */
 GEANY_API_SYMBOL
 const GSList *filetypes_get_sorted_by_name(void)
@@ -764,8 +771,8 @@ GeanyFiletype *filetypes_detect_from_document(GeanyDocument *doc)
  *
  *  @param utf8_filename The filename in UTF-8 encoding.
  *
- *  @return The detected filetype for @a utf8_filename or @c filetypes[GEANY_FILETYPES_NONE]
- *          if it could not be detected.
+ *  @return @transfer{none} The detected filetype for @a utf8_filename or
+ *           @c filetypes[GEANY_FILETYPES_NONE] if it could not be detected.
  **/
 GEANY_API_SYMBOL
 GeanyFiletype *filetypes_detect_from_file(const gchar *utf8_filename)
@@ -1246,7 +1253,7 @@ gboolean filetype_has_tags(GeanyFiletype *ft)
 
 /** Finds a filetype pointer from its @a name field.
  * @param name Filetype name.
- * @return The filetype found, or @c NULL.
+ * @return @transfer{none} @nullable The filetype found, or @c NULL.
  *
  * @since 0.15
  **/
@@ -1492,7 +1499,7 @@ void filetypes_reload_extensions(void)
 /** Accessor function for @ref GeanyData::filetypes_array items.
  * Example: @code ft = filetypes_index(GEANY_FILETYPES_C); @endcode
  * @param idx @c filetypes_array index.
- * @return The filetype, or @c NULL if @a idx is out of range.
+ * @return @transfer{none} @nullable The filetype, or @c NULL if @a idx is out of range.
  *
  *  @since 0.16
  */


Modified: src/filetypes.h
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -113,6 +113,10 @@ GeanyFiletypeID;
 
 #define filetype_id GeanyFiletypeID /* compat define - should be removed in the future */
 
+/** @gironly
+ * Filetype categories
+ *
+ * These are used to provide submenus for each category in the GUI */
 typedef enum
 {
 	GEANY_FILETYPE_GROUP_NONE,


Modified: src/keybindings.c
17 lines changed, 9 insertions(+), 8 deletions(-)
===================================================================
@@ -133,7 +133,7 @@ GdkModifierType keybindings_get_modifiers(GdkModifierType mods)
 /** Looks up a keybinding item.
  * @param group Group.
  * @param key_id Keybinding index for the group.
- * @return The keybinding.
+ * @return @transfer{none} The keybinding.
  * @since 0.19. */
 GEANY_API_SYMBOL
 GeanyKeyBinding *keybindings_get_item(GeanyKeyGroup *group, gsize key_id)
@@ -150,20 +150,21 @@ GeanyKeyBinding *keybindings_get_item(GeanyKeyGroup *group, gsize key_id)
 
 /* This is used to set default keybindings on startup.
  * Menu accels are set in apply_kb_accel(). */
-/** Fills a GeanyKeyBinding struct item.
+/** @girskip
+ * Fills a GeanyKeyBinding struct item.
  * @note Always set @a key and @a mod to 0, otherwise you will likely
  * cause conflicts with the user's custom, other plugin's keybindings or
  * future default keybindings.
  * @param group Group.
  * @param key_id Keybinding index for the group.
- * @param callback Function to call when activated, or @c NULL to use the group callback.
+ * @param callback @nullable Function to call when activated, or @c NULL to use the group callback.
  * Usually it's better to use the group callback instead - see plugin_set_key_group().
  * @param key Default key, e.g. @c GDK_j (must be lower case), but usually 0 for unset.
  * @param mod Default modifier, e.g. @c GDK_CONTROL_MASK, but usually 0 for unset.
  * @param kf_name Key name for the configuration file, such as @c "menu_new".
  * @param label Label used in the preferences dialog keybindings tab. May contain
  * underscores - these won't be displayed.
- * @param menu_item Optional widget to set an accelerator for, or @c NULL.
+ * @param menu_item @nullable Optional widget to set an accelerator for, or @c NULL.
  * @return The keybinding - normally this is ignored. */
 GEANY_API_SYMBOL
 GeanyKeyBinding *keybindings_set_item(GeanyKeyGroup *group, gsize key_id,
@@ -216,11 +217,11 @@ GeanyKeyBinding *keybindings_set_item(GeanyKeyGroup *group, gsize key_id,
  * @param kf_name Key name for the configuration file, such as @c "menu_new".
  * @param label Label used in the preferences dialog keybindings tab. May contain
  * underscores - these won't be displayed.
- * @param menu_item Optional widget to set an accelerator for, or @c NULL.
- * @param cb New-style callback to be called when activated, or @c NULL to use the group callback.
- * @param pdata Plugin-specific data passed back to the callback.
+ * @param menu_item @nullable Optional widget to set an accelerator for, or @c NULL.
+ * @param cb @nullable New-style callback to be called when activated, or @c NULL to use the group callback.
+ * @param pdata Plugin-specific data passed back to the callback @a cb.
  * @param destroy_notify Function that is invoked to free the plugin data when not needed anymore.
- * @return The keybinding - normally this is ignored.
+ * @return @transfer{none} The keybinding - normally this is ignored.
  *
  * @since 1.26 (API 226)
  * @see See plugin_set_key_group_full


Modified: src/plugindata.h
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -222,8 +222,8 @@ typedef struct GeanyData
 {
 	struct GeanyApp				*app;				/**< Geany application data fields */
 	struct GeanyMainWidgets		*main_widgets;		/**< Important widgets in the main window */
-	GPtrArray					*documents_array;	/**< See document.h#documents_array. */
-	GPtrArray					*filetypes_array;	/**< Dynamic array of GeanyFiletype pointers */
+	GPtrArray					*documents_array;	/**< See document.h#documents_array. @elementtype{GeanyDocument} */
+	GPtrArray					*filetypes_array;	/**< Dynamic array of GeanyFiletype pointers. @elementtype{GeanyFiletype} */
 	struct GeanyPrefs			*prefs;				/**< General settings */
 	struct GeanyInterfacePrefs	*interface_prefs;	/**< Interface settings */
 	struct GeanyToolbarPrefs	*toolbar_prefs;		/**< Toolbar settings */


Modified: src/pluginutils.c
37 lines changed, 22 insertions(+), 15 deletions(-)
===================================================================
@@ -102,9 +102,10 @@ void plugin_module_make_resident(GeanyPlugin *plugin)
 }
 
 
-/** Connects a signal which will be disconnected on unloading the plugin, to prevent a possible segfault.
+/** @girskip
+ * Connects a signal which will be disconnected on unloading the plugin, to prevent a possible segfault.
  * @param plugin Must be @ref geany_plugin.
- * @param object Object to connect to, or @c NULL when using @link pluginsignals.c Geany signals @endlink.
+ * @param object @nullable Object to connect to, or @c NULL when using @link pluginsignals.c Geany signals @endlink.
  * @param signal_name The name of the signal. For a list of available
  * signals, please see the @link pluginsignals.c Signal documentation @endlink.
  * @param after Set to @c TRUE to call your handler after the main signal handlers have been called
@@ -128,7 +129,8 @@ void plugin_module_make_resident(GeanyPlugin *plugin)
  *          object has been destroyed), and disconnect yourself or not as appropriate.
  * @note Since version 1.25 (API >= 218), the object lifetime is watched and so the above
  *       restriction does not apply.  However, for objects destroyed by the plugin,
- *       @c g_signal_connect() is safe and has lower overhead. */
+ *       @c g_signal_connect() is safe and has lower overhead.
+ **/
 GEANY_API_SYMBOL
 void plugin_signal_connect(GeanyPlugin *plugin,
 		GObject *object, const gchar *signal_name, gboolean after,
@@ -229,8 +231,9 @@ static guint plugin_source_add(GeanyPlugin *plugin, GSource *source, GSourceFunc
 }
 
 
-/** Adds a GLib main loop timeout callback that will be removed when unloading the plugin,
- *  preventing it to run after the plugin has been unloaded (which may lead to a segfault).
+/** @girskip
+ * Adds a GLib main loop timeout callback that will be removed when unloading the plugin,
+ * preventing it to run after the plugin has been unloaded (which may lead to a segfault).
  *
  * @param plugin Must be @ref geany_plugin.
  * @param interval The time between calls to the function, in milliseconds.
@@ -249,8 +252,9 @@ guint plugin_timeout_add(GeanyPlugin *plugin, guint interval, GSourceFunc functi
 }
 
 
-/** Adds a GLib main loop timeout callback that will be removed when unloading the plugin,
- *  preventing it to run after the plugin has been unloaded (which may lead to a segfault).
+/** @girskip
+ * Adds a GLib main loop timeout callback that will be removed when unloading the plugin,
+ * preventing it to run after the plugin has been unloaded (which may lead to a segfault).
  *
  * @param plugin Must be @ref geany_plugin.
  * @param interval The time between calls to the function, in seconds.
@@ -270,8 +274,9 @@ guint plugin_timeout_add_seconds(GeanyPlugin *plugin, guint interval, GSourceFun
 }
 
 
-/** Adds a GLib main loop IDLE callback that will be removed when unloading the plugin, preventing
- *  it to run after the plugin has been unloaded (which may lead to a segfault).
+/** @girskip
+ * Adds a GLib main loop IDLE callback that will be removed when unloading the plugin, preventing
+ * it to run after the plugin has been unloaded (which may lead to a segfault).
  *
  * @param plugin Must be @ref geany_plugin.
  * @param function The function to call in IDLE time.
@@ -289,14 +294,16 @@ guint plugin_idle_add(GeanyPlugin *plugin, GSourceFunc function, gpointer data)
 }
 
 
-/** Sets up or resizes a keybinding group for the plugin.
+/** @girskip
+ * Sets up or resizes a keybinding group for the plugin.
  * You should then call keybindings_set_item() for each keybinding in the group.
  * @param plugin Must be @ref geany_plugin.
  * @param section_name Name used in the configuration file, such as @c "html_chars".
  * @param count Number of keybindings for the group.
- * @param callback Group callback, or @c NULL if you only want individual keybinding callbacks.
+ * @param callback @nullable Group callback, or @c NULL if you only want individual keybinding callbacks.
  * @return The plugin's keybinding group.
- * @since 0.19. */
+ * @since 0.19.
+ **/
 GEANY_API_SYMBOL
 GeanyKeyGroup *plugin_set_key_group(GeanyPlugin *plugin,
 		const gchar *section_name, gsize count, GeanyKeyGroupCallback callback)
@@ -315,10 +322,10 @@ GeanyKeyGroup *plugin_set_key_group(GeanyPlugin *plugin,
  * @param plugin Must be @ref geany_plugin.
  * @param section_name Name used in the configuration file, such as @c "html_chars".
  * @param count Number of keybindings for the group.
- * @param cb New-style group callback, or @c NULL if you only want individual keybinding callbacks.
- * @param pdata Plugin specific data, passed to the group callback.
+ * @param cb @nullable New-style group callback, or @c NULL if you only want individual keybinding callbacks.
+ * @param pdata Plugin specific data, passed to the group callback @a cb.
  * @param destroy_notify Function that is invoked to free the plugin data when not needed anymore.
- * @return The plugin's keybinding group.
+ * @return @transfer{none} The plugin's keybinding group.
  *
  * @since 1.26 (API 226)
  * @see See keybindings_set_item


Modified: src/project.h
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -24,6 +24,7 @@
 #define GEANY_PROJECT_H 1
 
 #include <glib.h>
+#include <glib-object.h>
 
 G_BEGIN_DECLS
 
@@ -40,7 +41,7 @@ typedef struct GeanyProject
 	/** Identifier whether it is a pure Geany project or modified/extended
 	 * by a plugin. */
 	gint type;
-	gchar **file_patterns;	/**< Array of filename extension patterns. */
+	GStrv file_patterns;	/**< Array of filename extension patterns. */
 
 	struct GeanyProjectPrivate	*priv;	/* must be last, append fields before this item */
 }


Modified: src/search.h
9 lines changed, 6 insertions(+), 3 deletions(-)
===================================================================
@@ -43,12 +43,15 @@ typedef enum GeanyFindFlags
 }
 GeanyFindFlags;
 
-enum GeanyFindSelOptions
+/** @gironly
+ * Find selection options */
+typedef enum
 {
 	GEANY_FIND_SEL_CURRENT_WORD,
 	GEANY_FIND_SEL_X,
 	GEANY_FIND_SEL_AGAIN
-};
+}
+GeanyFindSelOptions;
 
 /** Search preferences */
 typedef struct GeanySearchPrefs
@@ -58,7 +61,7 @@ typedef struct GeanySearchPrefs
 	gboolean	use_current_file_dir;	/* find in files directory to use on showing dialog */
 	gboolean	hide_find_dialog;		/* hide the find dialog on next or previous */
 	gboolean	replace_and_find_by_default;	/* enter in replace window performs Replace & Find instead of Replace */
-	enum GeanyFindSelOptions find_selection_type;
+	GeanyFindSelOptions find_selection_type;
 }
 GeanySearchPrefs;
 


Modified: src/spawn.c
46 lines changed, 23 insertions(+), 23 deletions(-)
===================================================================
@@ -705,11 +705,11 @@ static gboolean spawn_async_with_pipes(const gchar *working_directory, const gch
  *
  *  If a @a child_pid is passed, it's your responsibility to invoke @c g_spawn_close_pid().
  *
- *  @param working_directory child's current working directory, or @c NULL.
- *  @param command_line child program and arguments, or @c NULL.
- *  @param argv child's argument vector, or @c NULL.
- *  @param envp child's environment, or @c NULL.
- *  @param child_pid return location for child process ID, or @c NULL.
+ *  @param working_directory @nullable child's current working directory, or @c NULL.
+ *  @param command_line @nullable child program and arguments, or @c NULL.
+ *  @param argv @nullable child's argument vector, or @c NULL.
+ *  @param envp @nullable child's environment, or @c NULL.
+ *  @param child_pid @out @optional return location for child process ID, or @c NULL.
  *  @param error return location for error.
  *
  *  @return @c TRUE on success, @c FALSE on error.
@@ -950,7 +950,7 @@ static void spawn_watch_cb(GPid pid, gint status, gpointer data)
 }
 
 
-/**
+/** @girskip
  *  Executes a child program and setups callbacks.
  *
  *  A command line or an argument vector must be passed. If both are present, the argument
@@ -978,22 +978,22 @@ static void spawn_watch_cb(GPid pid, gint status, gpointer data)
  *
  *  The @a child_pid will be closed automatically, after @a exit_cb is invoked.
  *
- *  @param working_directory child's current working directory, or @c NULL.
- *  @param command_line child program and arguments, or @c NULL.
- *  @param argv child's argument vector, or @c NULL.
- *  @param envp child's environment, or @c NULL.
+ *  @param working_directory @nullable child's current working directory, or @c NULL.
+ *  @param command_line @nullable child program and arguments, or @c NULL.
+ *  @param argv @nullable child's argument vector, or @c NULL.
+ *  @param envp @nullable child's environment, or @c NULL.
  *  @param spawn_flags flags from SpawnFlags.
- *  @param stdin_cb callback to send data to childs's stdin, or @c NULL.
+ *  @param stdin_cb @nullable callback to send data to childs's stdin, or @c NULL.
  *  @param stdin_data data to pass to @a stdin_cb.
- *  @param stdout_cb callback to receive child's stdout, or @c NULL.
+ *  @param stdout_cb @nullable callback to receive child's stdout, or @c NULL.
  *  @param stdout_data data to pass to @a stdout_cb.
  *  @param stdout_max_length maximum data length to pass to stdout_cb, @c 0 = default.
- *  @param stderr_cb callback to receive child's stderr, or @c NULL.
+ *  @param stderr_cb @nullable callback to receive child's stderr, or @c NULL.
  *  @param stderr_data data to pass to @a stderr_cb.
  *  @param stderr_max_length maximum data length to pass to stderr_cb, @c 0 = default.
- *  @param exit_cb callback to invoke when the child exits, or @c NULL.
+ *  @param exit_cb @nullable callback to invoke when the child exits, or @c NULL.
  *  @param exit_data data to pass to @a exit_cb.
- *  @param child_pid return location for child process ID, or @c NULL.
+ *  @param child_pid @out @optional return location for child process ID, or @c NULL.
  *  @param error return location for error.
  *
  *  @return @c TRUE on success, @c FALSE on error.
@@ -1183,14 +1183,14 @@ static void spawn_get_exit_status_cb(G_GNUC_UNUSED GPid pid, gint status, gpoint
  *  All output from the child, including the nul characters, is stored in @a stdout_data and
  *  @a stderr_data (if non-NULL). Any existing data in these strings will be erased.
  *
- *  @param working_directory child's current working directory, or @c NULL.
- *  @param command_line child program and arguments, or @c NULL.
- *  @param argv child's argument vector, or @c NULL.
- *  @param envp child's environment, or @c NULL.
- *  @param stdin_data data to send to childs's stdin, or @c NULL.
- *  @param stdout_data GString location to receive the child's stdout, or NULL.
- *  @param stderr_data GString location to receive the child's stderr, or NULL.
- *  @param exit_status return location for the child exit code, or NULL.
+ *  @param working_directory @nullable child's current working directory, or @c NULL.
+ *  @param command_line @nullable child program and arguments, or @c NULL.
+ *  @param argv @nullable child's argument vector, or @c NULL.
+ *  @param envp @nullable child's environment, or @c NULL.
+ *  @param stdin_data @nullable data to send to childs's stdin, or @c NULL.
+ *  @param stdout_data @nullable GString location to receive the child's stdout, or @c NULL.
+ *  @param stderr_data @nullable GString location to receive the child's stderr, or @c NULL.
+ *  @param exit_status @out @optional return location for the child exit code, or @c NULL.
  *  @param error return location for error.
  *
  *  @return @c TRUE on success, @c FALSE on error.


Modified: src/stash.c
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -495,7 +495,7 @@ void stash_group_add_integer(StashGroup *group, gint *setting,
  * @param group .
  * @param setting Address of setting variable.
  * @param key_name Name for key in a @c GKeyFile.
- * @param default_value String to copy if the key doesn't exist when loading, or @c NULL. */
+ * @param default_value @nullable String to copy if the key doesn't exist when loading, or @c NULL. */
 GEANY_API_SYMBOL
 void stash_group_add_string(StashGroup *group, gchar **setting,
 		const gchar *key_name, const gchar *default_value)


Modified: src/ui_utils.c
45 lines changed, 28 insertions(+), 17 deletions(-)
===================================================================
@@ -1461,7 +1461,10 @@ void ui_update_view_editor_menu_items(void)
 /** Creates a GNOME HIG-style frame (with no border and indented child alignment).
  * @param label_text The label text.
  * @param alignment An address to store the alignment widget pointer.
- * @return The frame widget, setting the alignment container for packing child widgets. */
+ *
+ * @return @transfer{floating} The frame widget, setting the alignment container for
+ * packing child widgets.
+ **/
 GEANY_API_SYMBOL
 GtkWidget *ui_frame_new_with_alignment(const gchar *label_text, GtkWidget **alignment)
 {
@@ -1484,7 +1487,8 @@ GtkWidget *ui_frame_new_with_alignment(const gchar *label_text, GtkWidget **alig
 
 /** Makes a fixed border for dialogs without increasing the button box border.
  * @param dialog The parent container for the @c GtkVBox.
- * @return The packed @c GtkVBox. */
+ *
+ * @return @transfer{none} The packed @c GtkVBox. */
 GEANY_API_SYMBOL
 GtkWidget *ui_dialog_vbox_new(GtkDialog *dialog)
 {
@@ -1535,7 +1539,8 @@ void ui_dialog_set_primary_button_order(GtkDialog *dialog, gint response, ...)
  * @c gtk_button_new_from_stock().
  * @param stock_id A @c GTK_STOCK_NAME string.
  * @param text Button label text, can include mnemonics.
- * @return The new @c GtkButton.
+ *
+ * @return @transfer{floating} The new @c GtkButton.
  */
 GEANY_API_SYMBOL
 GtkWidget *ui_button_new_with_image(const gchar *stock_id, const gchar *text)
@@ -1554,7 +1559,7 @@ GtkWidget *ui_button_new_with_image(const gchar *stock_id, const gchar *text)
 /** Creates a @c GtkImageMenuItem with a stock image and a custom label.
  * @param stock_id Stock image ID, e.g. @c GTK_STOCK_OPEN.
  * @param label Menu item label, can include mnemonics.
- * @return The new @c GtkImageMenuItem.
+ * @return @transfer{floating} The new @c GtkImageMenuItem.
  *
  *  @since 0.16
  */
@@ -1680,7 +1685,7 @@ static gboolean tree_model_find_text(GtkTreeModel *model,
 /** Prepends @a text to the drop down list, removing a duplicate element in
  * the list if found. Also ensures there are <= @a history_len elements.
  * @param combo_entry .
- * @param text Text to add, or @c NULL for current entry text.
+ * @param text @nullable Text to add, or @c NULL for current entry text.
  * @param history_len Max number of items, or @c 0 for default. */
 GEANY_API_SYMBOL
 void ui_combo_box_add_to_history(GtkComboBoxText *combo_entry,
@@ -1894,11 +1899,12 @@ void ui_widget_modify_font_from_string(GtkWidget *widget, const gchar *str)
  * file chooser, replacing entry text (if successful) with the path returned from the
  * @c GtkFileChooser.
  * @note @a entry can be the child of an unparented widget, such as @c GtkComboBoxEntry.
- * @param title The file chooser dialog title, or @c NULL.
+ * @param title @nullable The file chooser dialog title, or @c NULL.
  * @param action The mode of the file chooser.
  * @param entry Can be an unpacked @c GtkEntry, or the child of an unpacked widget,
  * such as @c GtkComboBoxEntry.
- * @return The @c GtkHBox.
+ *
+ * @return @transfer{floating} The @c GtkHBox.
  */
 /* @see ui_setup_open_button_callback(). */
 GEANY_API_SYMBOL
@@ -2651,7 +2657,8 @@ void ui_widget_set_tooltip_text(GtkWidget *widget, const gchar *text)
  * you want returned.
  * @param widget Widget with the @a widget_name property set.
  * @param widget_name Name to lookup.
- * @return The widget found.
+ *
+ * @return @transfer{none} The widget found.
  * @see ui_hookup_widget().
  *
  *  @since 0.16
@@ -2731,7 +2738,7 @@ static gboolean progress_bar_pulse(gpointer data)
  * In this case, you need to show and hide the widget yourself. You can find some example code
  * in @c src/printing.c.
  *
- * @param text The text to be shown as the progress bar label or NULL to leave it empty.
+ * @param text @nullable The text to be shown as the progress bar label or @c NULL to leave it empty.
  *
  *  @since 0.16
  **/
@@ -2836,13 +2843,15 @@ GtkWidget *ui_label_new_bold(const gchar *text)
 }
 
 
-/** Adds a list of document items to @a menu.
+/** @girskip
+ * Adds a list of document items to @a menu.
  * @param menu Menu.
- * @param active Which document to highlight, or @c NULL.
- * @param callback is used for each menu item's @c "activate" signal and will be passed
- * the corresponding document pointer as @c user_data.
+ * @param active @nullable Which document to highlight, or @c NULL.
+ * @param callback is used for each menu item's @c "activate" signal and will be
+ * passed the corresponding document pointer as @c user_data.
  * @warning You should check @c doc->is_valid in the callback.
- * @since 0.19 */
+ * @since 0.19
+ **/
 GEANY_API_SYMBOL
 void ui_menu_add_document_items(GtkMenu *menu, GeanyDocument *active, GCallback callback)
 {
@@ -2850,7 +2859,8 @@ void ui_menu_add_document_items(GtkMenu *menu, GeanyDocument *active, GCallback
 }
 
 
-/** Adds a list of document items to @a menu.
+/** @girskip
+ * Adds a list of document items to @a menu.
  *
  * @a compare_func might be NULL to not sort the documents in the menu. In this case,
  * the order of the document tabs is used.
@@ -2858,12 +2868,13 @@ void ui_menu_add_document_items(GtkMenu *menu, GeanyDocument *active, GCallback
  * See document_compare_by_display_name() for an example sort function.
  *
  * @param menu Menu.
- * @param active Which document to highlight, or @c NULL.
+ * @param active @nullable Which document to highlight, or @c NULL.
  * @param callback is used for each menu item's @c "activate" signal and will be passed
  * the corresponding document pointer as @c user_data.
  * @param compare_func is used to sort the list. Might be @c NULL to not sort the list.
  * @warning You should check @c doc->is_valid in the callback.
- * @since 0.21 */
+ * @since 0.21
+ **/
 GEANY_API_SYMBOL
 void ui_menu_add_document_items_sorted(GtkMenu *menu, GeanyDocument *active,
 	GCallback callback, GCompareFunc compare_func)


Modified: src/utils.c
46 lines changed, 23 insertions(+), 23 deletions(-)
===================================================================
@@ -263,7 +263,7 @@ gint utils_write_file(const gchar *filename, const gchar *text)
 /** Searches backward through @a size bytes looking for a '<'.
  * @param sel .
  * @param size .
- * @return The tag name (newly allocated) or @c NULL if no opening tag was found.
+ * @return @nullable The tag name (newly allocated) or @c NULL if no opening tag was found.
  */
 GEANY_API_SYMBOL
 gchar *utils_find_open_xml_tag(const gchar sel[], gint size)
@@ -288,7 +288,7 @@ gchar *utils_find_open_xml_tag(const gchar sel[], gint size)
 /** Searches backward through @a size bytes looking for a '<'.
  * @param sel .
  * @param size .
- * @return pointer to '<' of the found opening tag within @a sel, or @c NULL if no opening tag was found.
+ * @return @nullable pointer to '<' of the found opening tag within @a sel, or @c NULL if no opening tag was found.
  */
 GEANY_API_SYMBOL
 const gchar *utils_find_open_xml_tag_pos(const gchar sel[], gint size)
@@ -490,8 +490,8 @@ static gchar *utf8_strdown(const gchar *str)
  *
  *  The input strings should be in UTF-8 or locale encoding.
  *
- *  @param s1 Pointer to first string or @c NULL.
- *  @param s2 Pointer to second string or @c NULL.
+ *  @param s1 @nullable Pointer to first string or @c NULL.
+ *  @param s2 @nullable Pointer to second string or @c NULL.
  *
  *  @return an integer less than, equal to, or greater than zero if @a s1 is found, respectively,
  *          to be less than, to match, or to be greater than @a s2.
@@ -586,8 +586,8 @@ gchar *utils_str_middle_truncate(const gchar *string, guint truncate_length)
  *  @c NULL-safe string comparison. Returns @c TRUE if both @a a and @a b are @c NULL
  *  or if @a a and @a b refer to valid strings which are equal.
  *
- *  @param a Pointer to first string or @c NULL.
- *  @param b Pointer to second string or @c NULL.
+ *  @param a @nullable Pointer to first string or @c NULL.
+ *  @param b @nullable Pointer to second string or @c NULL.
  *
  *  @return @c TRUE if @a a equals @a b, else @c FALSE.
  **/
@@ -722,7 +722,7 @@ gint utils_strpos(const gchar *haystack, const gchar *needle)
  *
  *  @param format The format string to pass to strftime(3). See the strftime(3)
  *                documentation for details, in UTF-8 encoding.
- *  @param time_to_use The date/time to use, in time_t format or NULL to use the current time.
+ *  @param time_to_use @nullable The date/time to use, in time_t format or @c NULL to use the current time.
  *
  *  @return A newly-allocated string, should be freed when no longer needed.
  *
@@ -1405,8 +1405,8 @@ gint utils_mkdir(const gchar *path, gboolean create_parent_dirs)
  * @param sort Whether to sort alphabetically (UTF-8 safe).
  * @param error The location for storing a possible error, or @c NULL.
  *
- * @return A newly allocated list or @c NULL if no files were found. The list and its data should be
- * freed when no longer needed.
+ * @return @elementtype{filename} @transfer{full} @nullable A newly allocated list or @c NULL if
+ * no files were found. The list and its data should be freed when no longer needed.
  * @see utils_get_file_list().
  **/
 GEANY_API_SYMBOL
@@ -1450,8 +1450,8 @@ GSList *utils_get_file_list_full(const gchar *path, gboolean full_path, gboolean
  *               unless @c NULL.
  * @param error The location for storing a possible error, or @c NULL.
  *
- * @return A newly allocated list or @c NULL if no files were found. The list and its data should be
- *         freed when no longer needed.
+ * @return @elementtype{filename} @transfer{full} @nullable A newly allocated list or @c NULL
+ * if no files were found. The list and its data should be freed when no longer needed.
  * @see utils_get_file_list_full().
  **/
 GEANY_API_SYMBOL
@@ -1647,15 +1647,15 @@ const gchar *utils_get_default_dir_utf8(void)
 /**
  *  Wraps @c spawn_sync(), which see.
  *
- *  @param dir The child's current working directory, or @c NULL to inherit parent's.
+ *  @param dir @nullable The child's current working directory, or @c NULL to inherit parent's.
  *  @param argv The child's argument vector.
- *  @param env The child's environment, or @c NULL to inherit parent's.
+ *  @param env @nullable The child's environment, or @c NULL to inherit parent's.
  *  @param flags Ignored.
- *  @param child_setup Ignored.
- *  @param user_data Ignored.
- *  @param std_out The return location for child output, or @c NULL.
- *  @param std_err The return location for child error messages, or @c NULL.
- *  @param exit_status The child exit status, as returned by waitpid(), or @c NULL.
+ *  @param child_setup @girskip Ignored.
+ *  @param user_data @girskip Ignored.
+ *  @param std_out @out @optional The return location for child output, or @c NULL.
+ *  @param std_err @out @optional The return location for child error messages, or @c NULL.
+ *  @param exit_status @out @optional The child exit status, as returned by waitpid(), or @c NULL.
  *  @param error The return location for error or @c NULL.
  *
  *  @return @c TRUE on success, @c FALSE if an error was set.
@@ -1682,13 +1682,13 @@ gboolean utils_spawn_sync(const gchar *dir, gchar **argv, gchar **env, GSpawnFla
 /**
  *  Wraps @c spawn_async(), which see.
  *
- *  @param dir The child's current working directory, or @c NULL to inherit parent's.
+ *  @param dir @nullable The child's current working directory, or @c NULL to inherit parent's.
  *  @param argv The child's argument vector.
- *  @param env The child's environment, or @c NULL to inherit parent's.
+ *  @param env @nullable The child's environment, or @c NULL to inherit parent's.
  *  @param flags Ignored.
- *  @param child_setup Ignored.
+ *  @param child_setup @girskip Ignored.
  *  @param user_data Ignored.
- *  @param child_pid The return location for child process ID, or NULL.
+ *  @param child_pid @nullable The return location for child process ID, or @c NULL.
  *  @param error The return location for error or @c NULL.
  *
  *  @return @c TRUE on success, @c FALSE if an error was set.
@@ -1959,7 +1959,7 @@ static gboolean str_in_array(const gchar **haystack, const gchar *needle)
  * @param first_varname Name of the first variable to copy into the new array.
  * @param ... Key-value pairs of variable names and values, @c NULL-terminated.
  *
- * @return The new environment array. Use @c g_strfreev() to free it.
+ * @return @transfer{full} The new environment array. Use @c g_strfreev() to free it.
  **/
 GEANY_API_SYMBOL
 gchar **utils_copy_environment(const gchar **exclude_vars, const gchar *first_varname, ...)


Modified: tagmanager/src/tm_workspace.c
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -279,7 +279,7 @@ static void tm_workspace_update(void)
 /** Adds multiple source files to the workspace and updates the workspace tag arrays.
  This is more efficient than calling tm_workspace_add_source_file() and
  tm_workspace_update_source_file() separately for each of the files.
- @param source_files The source files to be added to the workspace.
+ @param source_files @elementtype{TMSourceFile} The source files to be added to the workspace.
 */
 GEANY_API_SYMBOL
 void tm_workspace_add_source_files(GPtrArray *source_files)
@@ -304,7 +304,7 @@ void tm_workspace_add_source_files(GPtrArray *source_files)
  arrays. This is more efficient than calling tm_workspace_remove_source_file()
  separately for each of the files. To completely free the TMSourceFile pointers
  call tm_source_file_free() on each of them.
- @param source_files The source files to be removed from the workspace.
+ @param source_files @elementtype{TMSourceFile} The source files to be removed from the workspace.
 */
 GEANY_API_SYMBOL
 void tm_workspace_remove_source_files(GPtrArray *source_files)



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list