summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS3
-rw-r--r--ChangeLog0
-rw-r--r--Makefile.am16
-rw-r--r--NEWS0
-rw-r--r--README137
-rw-r--r--acconfig.h25
-rwxr-xr-xautogen.sh66
-rw-r--r--configure.in52
-rw-r--r--db2man/README14
-rwxr-xr-xdb2man/docbook-to-man178
-rw-r--r--db2man/docbook-to-man.ts2019
-rw-r--r--doc/README26
-rw-r--r--doc/authors.txt174
-rw-r--r--doc/gnome.txt79
-rw-r--r--doc/gtk_button.txt235
-rw-r--r--doc/manpage170
-rw-r--r--doc/manpage.man140
-rw-r--r--doc/notes.txt180
-rw-r--r--gtk-doc.cat4
-rw-r--r--gtk-doc.dsl.in206
-rw-r--r--gtk-doc.dtd10
-rwxr-xr-xgtkdoc-mkdb1159
-rw-r--r--gtkdoc-mkhtml.in19
-rw-r--r--gtkdoc-mkman.in27
-rwxr-xr-xgtkdoc-mktmpl466
-rwxr-xr-xgtkdoc-scan381
-rwxr-xr-xgtkdoc-scanobj680
27 files changed, 6466 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..344c169
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
+Damon Chaplin <DAChaplin@msn.com>
+Owen Taylor <otaylor@redhat.com>
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..503bb2d
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,16 @@
+## Process this file with automake to produce Makefile.in
+
+bin_SCRIPTS = \
+ gtkdoc-scanobj \
+ gtkdoc-scan \
+ gtkdoc-mktmpl \
+ gtkdoc-mkdb \
+ gtkdoc-mkhtml \
+ gtkdoc-mkman
+
+gtkdocdatadir = $(datadir)/gtk-doc
+gtkdocdata_DATA = \
+ gtk-doc.dtd \
+ gtk-doc.dsl \
+ gtk-doc.cat
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..9c8d6fc
--- /dev/null
+++ b/README
@@ -0,0 +1,137 @@
+
+GTK+ DocBook Documentation Generator
+====================================
+
+This package automatically generates DocBook documentation for GTK+,
+and converts the DocBook documentation into HTML and man pages.
+
+There a few hard-coded paths in the scripts:
+ scan-gtk-perl/scangtk.pl
+ scan-gtk-c/getinits.pl
+ db2man/docbook-to-man
+ gtk-doc.dsl
+ mkgtkdb.pl
+ mkgtkhtml
+ mkgtktmpl.pl
+
+Also, some scripts expect certain directories to be created.
+
+
+Requirements
+============
+
+Perl v5 - the main scripts are in Perl, which is expected to be in /usr/bin.
+ You'll have to change the first lines, "!#/usr/bin/perl" if it isn't.
+
+DocBook DTD v3.0 - This is the DocBook SGML DTD.
+ http://www.ora.com/davenport
+
+Jade v1.1 - This is a DSSSL processor for converting SGML to various formats.
+ http://www.jclark.com/jade
+
+Modular DocBook Stylesheets (I've got 1.20, but v1.08+ should be OK)
+ This is the DSSSL code to convert DocBook to HTML (and a few other
+ formats). It's used together with jade.
+ I've customized the DSSSL code slightly, in gtk-doc.dsl, to stop the
+ output of the main table of contents, and to add a border and colour to
+ the program code listings/declarations.
+ http://nwalsh.com/docbook/dsssl
+
+docbook-to-man - This converts the DocBook into man pages. I've customized
+ the 'translation spec' slightly, to capitalise section headings and add
+ the 'GTK Library' title at the top of the pages and the revision date
+ at the bottom.
+ There is a link to this on http://www.ora.com/davenport
+
+
+[ The rest of the information in this file is out of date and
+ needs to be updated. See ftp://ftp.gtk.org/pub/users/otaylor/gtk-doc/
+ for some examples of documentation packages using the scripts
+ in this module. ]
+
+Overview
+========
+
+These are the stages for producing the final HTML/man pages.
+I've already scanned GLib 1.1.4 and GTK 1.1.3 so you can skip steps 1 & 2
+for now. See the later section for resyncing the documentation with the code.
+
+
+1. Scanning GTK, to get function prototypes, structs, enums, macros etc.
+
+ 1.1. In the scan-gtk-c directory run getinits.pl to create inits.c
+ (Note: the script includes hard-coded paths which must be updated)
+ Compile the getgtkinfo C program and run it to generate signals.txt
+ and hierarchy.txt
+
+ 1.2. Run scan-gtk-perl/scangtk.pl which scans the GTK header files and
+ outputs files describing all the function/macro etc. declarations found.
+ The gXXX-decl.txt files contain the full declarations.
+ The gXXX-decl-list.txt files contain a list of the declaration names,
+ and possibly section headings.
+
+ 1.4. Copy the gXXX-decl-list.txt files to gXXX-sections.txt and hand-edit
+ these to rearrange the items and split into sections.
+
+
+2. Creating blank template files.
+
+ Run mkgtktmpl.pl to create empty templates for each function etc.
+ (Note: the script includes hard-coded paths which must be updated)
+ It won't overwrite files, since you may lose work, so if you need to
+ regenerate the blank documents you need to delete the current files.
+
+
+3. Manually editing documentation in gtkdocs/ directory.
+
+ See doc/authors.txt for a description of the abbreviations and DocBook
+ tags which can be used.
+
+
+4. Creating the DocBook files and then the HTML or man pages.
+
+ 4.1. Run mkgtkdb.pl to generate the DocBook sgml files.
+ (Note: the script includes hard-coded paths which must be updated)
+
+ 4.2. If any new files have been added, you must recreate the main DocBook
+ document, sgml/gtk-docs.sgml. This should include all the entities
+ generated in sgml/gXXX-doc.top & sgml/gXXX-doc.bottom.
+
+ 4.3. Run mkgtkhtml to generate the HTML from the DocBook.
+ (Note: the script includes hard-coded paths which must be updated)
+ This uses the DSSSL file gtk-doc.dsl, which also has hard-coded paths.
+ Note that it complains a lot about references to non-existent IDs, but
+ it still works OK.
+
+ 4.4. Run mkgtkman to generate the man pages from the DocBook files.
+ I customized docbook-to-man slightly. The script and transpec I use are
+ in db2man.
+
+
+
+Resyncing the Documentation with New Versions of GTK/GLib
+=========================================================
+
+(This should be made simpler somehow)
+
+Scan GTK or GLib again, as in (1) above.
+
+Compare the new gXXX-decl.txt files with the backups gXXX-decl.bak to
+see which functions/macros etc. have been added or changed.
+If an existing function prototype has been changed you will have to edit the
+bits in the gtkdocs directory to bring them up to date.
+
+Update the gXXX-sections.txt to include the new functions etc. in the
+appropriate sections.
+
+Add the new templates to the gtkdocs/ files. (I usually run mkgtktmpl.pl
+with a different output directory and copy the new templates across.)
+
+Run mkgtkdb.pl to generate the DocBook. It will complain about missing
+pieces and will output unused declarations to gXXX-unused.txt so you can
+go back and fix these and run it again until it is all OK.
+(Note: Currently I don't use the GTK object structs in the documentation so
+these always appear in gtk-unused.txt)
+
+
+Damon Chaplin (DAChaplin@msn.com), 10 Nov 1998.
diff --git a/acconfig.h b/acconfig.h
new file mode 100644
index 0000000..1b4a6ef
--- /dev/null
+++ b/acconfig.h
@@ -0,0 +1,25 @@
+/* acconfig.h
+ This file is in the public domain.
+
+ Descriptive text for the C preprocessor macros that
+ the distributed Autoconf macros can define.
+ No software package will use all of them; autoheader copies the ones
+ your configure.in uses into your configuration header file templates.
+
+ The entries are in sort -df order: alphabetical, case insensitive,
+ ignoring punctuation (such as underscores). Although this order
+ can split up related entries, it makes it easier to check whether
+ a given entry is in the file.
+
+ Leave the following blank line there!! Autoheader needs it. */
+
+
+/* Other stuff */
+/* #undef PACKAGE */
+/* #undef VERSION */
+
+
+/* Leave that blank line there!! Autoheader needs it.
+ If you're adding to this file, keep in mind:
+ The entries are in sort -df order: alphabetical, case insensitive,
+ ignoring punctuation (such as underscores). */
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..5fa15e8
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+PROJECT=gtk-doc
+TEST_TYPE=-f
+FILE=gtk-doc.dtd
+
+DIE=0
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have autoconf installed to compile $PROJECT."
+ echo "Download the appropriate package for your distribution,"
+ echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+}
+
+(libtool --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have libtool installed to compile $PROJECT."
+ echo "Get ftp://alpha.gnu.org/gnu/libtool-1.2b.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+}
+
+(automake --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have automake installed to compile $PROJECT."
+ echo "Get ftp://ftp.cygnus.com/pub/home/tromey/automake-1.2d.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+}
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+ echo "You must run this script in the top-level $PROJECT directory"
+ exit 1
+}
+
+if test -z "$*"; then
+ echo "I am going to run ./configure with no arguments - if you wish "
+ echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+case $CC in
+*xlc | *xlc\ * | *lcc | *lcc\ *) am_opt=--include-deps;;
+esac
+
+aclocal $ACLOCAL_FLAGS
+
+# optionally feature autoheader
+(autoheader --version) < /dev/null > /dev/null 2>&1 && autoheader
+
+automake $am_opt
+autoconf
+
+./configure "$@"
+
+echo
+echo "Now type 'make' to compile $PROJECT."
+
+
+
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..4454e35
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,52 @@
+dnl Process this file with autoconf to produce a configure script.
+
+AC_INIT(gtk-doc.dtd)
+
+AM_INIT_AUTOMAKE(gtk-doc, 0.1)
+
+AC_ARG_WITH(dsssl-dir, [ --with-dsssl-dir=PATH path to DocBook style sheets ])
+
+AC_ISC_POSIX
+AC_PROG_CC
+
+if test "x$with_dsssl_dir" = "x" ; then
+ dirs="/usr/lib/sgml/stylesheets/nwalsh-modular /usr/lib/dsssl/stylesheets/docbook"
+else
+ dirs=$with_dsssl_dir
+fi
+
+AC_MSG_CHECKING([for DocBook stylesheets])
+
+DSSSL_DIR=""
+for i in $dirs ; do
+ if test -f $i/html/docbook.dsl ; then
+ DSSSL_DIR=$i
+ fi
+done
+
+if test "x$DSSSL_DIR" = x ; then
+ AC_MSG_ERROR([
+*** Cannot find DocBook stylesheets in "$dirs".
+*** Perhaps you need to specify the --with-dsssl-dir=PATH option?])
+fi
+
+AC_SUBST(DSSSL_DIR)
+
+AC_MSG_RESULT(found)
+
+dnl GTK 1.0.2 is needed for g_strdown(), GPOINTER_TO_INT macros, and
+dnl the header file <gtk/features.h> which gives us the GTK version.
+AM_PATH_GTK(1.0.2,
+ [LIBS="$LIBS $GTK_LIBS"
+ CFLAGS="$CFLAGS $GTK_CFLAGS"],
+ AC_MSG_ERROR(Cannot find GTK: Is gtk-config in path?))
+
+dnl Only use -Wall if we have gcc
+if test "x$GCC" = "xyes"; then
+ if test -z "`echo "$CFLAGS" | grep "\-Wall" 2> /dev/null`" ; then
+ CFLAGS="$CFLAGS -Wall"
+ fi
+fi
+
+AC_OUTPUT([Makefile gtk-doc.dsl gtkdoc-mkman gtkdoc-mkhtml gtkdoc-install],
+[chmod +x gtkdoc-mkman gtkdoc-mkhtml])
diff --git a/db2man/README b/db2man/README
new file mode 100644
index 0000000..6c48fc2
--- /dev/null
+++ b/db2man/README
@@ -0,0 +1,14 @@
+
+FILES
+=====
+
+docbook-to-man
+ my customized version of the docbook-to-man script. Note that it has
+ paths in it that you may need to change.
+ I also used the PROLOG stuff to specify the DocBook DTD when passing
+ the man pages to instant.
+
+docbook-to-man.ts
+ my customized version of the instant 'translation spec'.
+ I added support for the central title at the top of the pages, and the
+ revision date at the end. I also converted section 1 headings to all caps. \ No newline at end of file
diff --git a/db2man/docbook-to-man b/db2man/docbook-to-man
new file mode 100755
index 0000000..fd85da6
--- /dev/null
+++ b/db2man/docbook-to-man
@@ -0,0 +1,178 @@
+#!/bin/sh
+#############################################################################
+#
+# docbook-to-man.sh
+#
+#############################################################################
+#
+# Copyright (c) 1996 X Consortium
+# Copyright (c) 1996 Dalrymple Consulting
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM OR DALRYMPLE CONSULTING BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the names of the X Consortium and
+# Dalrymple Consulting shall not be used in advertising or otherwise to
+# promote the sale, use or other dealings in this Software without prior
+# written authorization.
+#
+#############################################################################
+#
+# Written 5/29/96 by Fred Dalrymple
+#
+#############################################################################
+
+# ***** change the following paths if your installation of nsgmls and / or
+# ***** DocBook isn't into the default places.
+
+ROOT=/usr
+SGMLS=$ROOT/lib/sgml
+DOCBOOK=$SGMLS/davenport
+
+
+# ***** modify the following line (to "=false") if you're not using the
+# ***** Elan Documentor's Workbench
+
+doElanPSInclude=false
+
+
+
+# Everything below this line should be pretty standard and not require
+# modification.
+
+#ulimit -c unlimited
+
+PARSER=nsgmls
+INSTANT=instant
+INSTANT_OPT=-d
+
+#CATALOG=$DOCBOOK/docbook.cat
+CATALOG=/etc/sgml.catalog
+DECL=$DOCBOOK/docbook.dcl
+
+error=false
+
+if [ $# -eq 1 ]
+then INSTANCE=$1
+else error=true
+fi
+
+if `$error`
+then echo "usage: docbook-to-man docbook-instance"
+ exit 1
+fi
+
+if `$doElanPSInclude`
+then cat > /tmp/dtm.$$.psinc <<\!
+...\" $Header$
+...\"
+...\" transcript compatibility for postscript use.
+...\"
+...\" synopsis: .P! <file.ps>
+...\"
+.de P!
+\\&.
+.fl \" force out current output buffer
+\\!%PB
+\\!/showpage{}def
+...\" the following is from Ken Flowers -- it prevents dictionary overflows
+\\!/tempdict 200 dict def tempdict begin
+.fl \" prolog
+.sy cat \\$1\" bring in postscript file
+...\" the following line matches the tempdict above
+\\!end % tempdict %
+\\!PE
+\\!.
+.sp \\$2u \" move below the image
+..
+!
+else cat > /tmp/dtm.$$.psinc <<\!
+...\" $Header$
+...\"
+...\" transcript compatibility for postscript use.
+...\"
+...\" synopsis: .P! <file.ps>
+...\"
+.de P!
+.fl
+\!!1 setgray
+.fl
+\\&.\"
+.fl
+\!!0 setgray
+.fl \" force out current output buffer
+\!!save /psv exch def currentpoint translate 0 0 moveto
+\!!/showpage{}def
+.fl \" prolog
+.sy sed -e 's/^/!/' \\$1\" bring in postscript file
+\!!psv restore
+.
+!
+fi
+
+cat >> /tmp/dtm.$$.psinc <<\!
+.de pF
+.ie \\*(f1 .ds f1 \\n(.f
+.el .ie \\*(f2 .ds f2 \\n(.f
+.el .ie \\*(f3 .ds f3 \\n(.f
+.el .ie \\*(f4 .ds f4 \\n(.f
+.el .tm ? font overflow
+.ft \\$1
+..
+.de fP
+.ie !\\*(f4 \{\
+. ft \\*(f4
+. ds f4\"
+' br \}
+.el .ie !\\*(f3 \{\
+. ft \\*(f3
+. ds f3\"
+' br \}
+.el .ie !\\*(f2 \{\
+. ft \\*(f2
+. ds f2\"
+' br \}
+.el .ie !\\*(f1 \{\
+. ft \\*(f1
+. ds f1\"
+' br \}
+.el .tm ? font underflow
+..
+.ds f1\"
+.ds f2\"
+.ds f3\"
+.ds f4\"
+!
+
+
+cat > /tmp/dtm.$$.prolog <<!
+<!DOCTYPE RefEntry PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
+<!ENTITY npzwc "">
+]>
+!
+
+(cat /tmp/dtm.$$.psinc;
+ $PARSER -gl -wno-idref -m$CATALOG $DECL /tmp/dtm.$$.prolog $INSTANCE |
+ $INSTANT $INSTANT_OPT -croff.cmap -sroff.sdata -tdocbook-to-man.ts)
+
+#(cat /tmp/dtm.$$.psinc;
+# $PARSER -gl -wno-idref -m$CATALOG $DECL $INSTANCE |
+# $INSTANT $INSTANT_OPT -croff.cmap -sroff.sdata -tdocbook-to-man.ts)
+
+rm -f /tmp/dtm.$$.psinc
+rm -f /tmp/dtm.$$.prolog
diff --git a/db2man/docbook-to-man.ts b/db2man/docbook-to-man.ts
new file mode 100644
index 0000000..7faa417
--- /dev/null
+++ b/db2man/docbook-to-man.ts
@@ -0,0 +1,2019 @@
+#############################################################################
+#
+# docbook-to-man.ts
+#
+#############################################################################
+#
+# Copyright (c) 1996 X Consortium
+# Copyright (c) 1996 Dalrymple Consulting
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM OR DALRYMPLE CONSULTING BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the names of the X Consortium and
+# Dalrymple Consulting shall not be used in advertising or otherwise to
+# promote the sale, use or other dealings in this Software without prior
+# written authorization.
+#
+#############################################################################
+#
+# Written 5/29/96 by Fred Dalrymple
+#
+#############################################################################
+#
+# Variables
+#
+Var: callout 0
+Var: orderlist 0
+Var: procstep 0
+Var: procsubstep 0
+#
+#
+#
+#
+#############################################################################
+#
+# Hierarchy (and document meta stuff)
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: REFENTRY
+StartText: ^.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n
+ ^.TH "${_followrel descendant REFENTRYTITLE 1000}"
+ "${_followrel descendant MANVOLNUM 1000}"
+ "${REVISION}" ""
+ "${_followrel descendant REFMISCINFO 1000}"^
+EndText: ^...\\" created by instant / docbook-to-man, ${date}^
+-
+#
+GI: DOCINFO
+Ignore: all
+-
+#
+GI: TITLE
+Context: DOCINFO
+# inside DocInfo, which we're ignoring
+-
+#
+GI: REFMETA
+Ignore: all
+-
+#
+GI: REFNAMEDIV
+StartText: ^.SH "NAME"^
+-
+#
+GI: REFDESCRIPTOR
+StartText: \\fB
+EndText: \\fR\s
+-
+#
+GI: REFNAME
+Relation: sibling- REFDESCRIPTOR
+# inhibit REFNAMEs when a REFDESCRIPTOR is present
+Ignore: all
+-
+#
+GI: REFNAME
+StartText: ${_isset refnameseen xxx 20}
+EndText: ${_set refnameseen xxx}
+-
+#
+GI: _refname
+SpecID: 20
+StartText: ,\s
+-
+#
+GI: REFPURPOSE
+StartText: \s\\-\s
+EndText: ^
+-
+#
+GI: REFCLASS
+StartText: ^.PP^
+EndText: ^
+-
+#
+GI: REFSYNOPSISDIV
+StartText: ^.SH "SYNOPSIS"^
+EndText: ^
+-
+#
+GI: REFSECT1
+StartText: ^.SH "${_followrel child TITLE 1001}"^
+EndText: ^
+-
+#
+GI: REFSECT2
+StartText: ^.SS "${_followrel child TITLE 1000}"^
+EndText: ^
+-
+#
+GI: REFSECT3
+StartText: ^.SS "${_followrel child TITLE 1000}"^
+EndText: ^
+-
+#
+GI: BRIDGEHEAD
+StartText: ^.PP^\\fB
+EndText: \\fP^.PP^
+-
+#
+GI: TITLE
+Context: REFSECT1
+Ignore: all
+-
+#
+GI: TITLE
+Context: REFSECT2
+Ignore: all
+-
+#
+GI: TITLE
+Context: REFSECT3
+Ignore: all
+-
+#
+GI: LEGALNOTICE
+# part of the DocInfo structure, which is ignored
+Ignore: all
+-
+#
+GI: TITLE
+Context: LEGALNOTICE
+# part of the DocInfo structure, which is ignored
+Ignore: all
+-
+#
+GI: REFENTRYTITLE
+Context: REFMETA
+# part of the DocInfo structure, which is ignored
+Ignore: all
+-
+#
+GI: MANVOLNUM
+Context: REFMETA
+# part of the DocInfo structure, which is ignored, though this element
+# if accessed directly by the _followrel call from the REFENTRY element.
+Ignore: all
+-
+#
+GI: REFMISCINFO
+# part of the DocInfo structure, which is ignored
+Ignore: all
+-
+#
+GI: SUBTITLE
+# part of the DocInfo structure, which is ignored
+Ignore: all
+-
+#
+GI: AUTHORGROUP
+# part of the DocInfo structure, which is ignored
+Ignore: all
+-
+#
+GI: AUTHOR
+Context: AUTHORGROUP
+# part of the DocInfo structure, which is ignored
+Ignore: all
+-
+#
+GI: EDITOR
+Context: AUTHORGROUP
+# part of the DocInfo structure, which is ignored
+Ignore: all
+-
+#
+GI: COLLAB
+Context: AUTHORGROUP
+# part of the DocInfo structure, which is ignored
+Ignore: all
+-
+#
+GI: COLLABNAME
+Context: COLLAB
+# part of the DocInfo structure, which is ignored
+Ignore: all
+-
+#
+GI: CORPAUTHOR
+Context: AUTHORGROUP
+# part of the DocInfo structure, which is ignored
+Ignore: all
+-
+#
+GI: OTHERCREDIT
+Context: AUTHORGROUP
+# part of the DocInfo structure, which is ignored
+Ignore: all
+-
+#
+#
+#############################################################################
+#
+# (before we get into the branch stuff, we turn off paragraphs in some
+# contexts where they would break the flow. Generally, this happens
+# within indented areas, such as within lists.
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: PARA
+Context: LISTITEM
+NthChild: 1
+# nothing in this context
+-
+#
+GI: PARA
+Context: GLOSSDEF
+NthChild: 1
+# nothing in this context
+-
+#
+GI: PARA
+Context: STEP
+NthChild: 1
+# nothing in this context
+-
+#
+GI: PARA
+Context: CALLOUT
+NthChild: 1
+# nothing in this context
+-
+#
+GI: PARA
+Context: MSGTEXT
+NthChild: 1
+# nothing in this context
+-
+#
+GI: PARA
+Relation: parent ENTRY
+NthChild: 1
+# first one does nothing in this context
+-
+#
+GI: PARA
+Relation: parent ENTRY
+StartText: ^.br^
+-
+#
+#
+#
+#############################################################################
+#
+# Regular "branch" stuff
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: FORMALPARA
+# it's all done in TITLE (FORMALPARA) and PARA
+-
+#
+GI: TITLE
+Context: FORMALPARA
+StartText: ^.PP^\\fB
+EndText: \\fR^
+-
+#
+GI: PARA
+Relation: ancestor LISTITEM
+StartText: ^.IP "" 10^
+-
+#
+GI: PARA
+Relation: ancestor STEP
+StartText: ^.IP "" 10^
+-
+#
+GI: PARA
+StartText: ^.PP^
+-
+#
+GI: SIMPARA
+StartText: ^.PP^
+-
+#
+GI: PROGRAMLISTING
+StartText: ^.PP^.nf^\\f(CW
+EndText: \\fR^.fi^.PP^
+-
+#
+GI: LITERALLAYOUT
+StartText: ^.PP^.nf^
+EndText: ^.fi^
+-
+#
+GI: BLOCKQUOTE
+StartText: ^.PP^.RS^
+EndText: ^.RE^
+-
+#
+GI: TITLE
+Context: BLOCKQUOTE
+StartText: ^\\fB
+EndText: \\fR^.PP^
+-
+#
+GI: EPIGRAPH
+StartText: ^.PP^.RS^
+EndText: ^.RE^
+-
+#
+GI: ATTRIBUTION
+StartText: ^\\fI
+EndText: \\fR^.PP^
+-
+#
+GI: ABSTRACT
+Relation: child TITLE
+-
+#
+GI: ABSTRACT
+StartText: ^.SS "Abstract"^
+-
+#
+GI: TITLE
+Context: ABSTRACT
+StartText: ^.SS "
+EndText: "^
+Substitute: " ""
+-
+#
+GI: REVHISTORY
+StartText: ^.SS "Revision History"^
+EndText: ^
+-
+#
+GI: REVISION
+StartText: ^.PP^\\fBRevision:\\fR\s
+EndText: ^
+-
+#
+GI: REVNUMBER
+StartText: #\s
+EndText: ;\s
+-
+#
+GI: DATE
+EndText: ;\s
+-
+#
+GI: AUTHORINITIALS
+Context: REVISION
+StartText: \s
+-
+#
+GI: REVREMARK
+StartText: ;\s\s
+EndText: ^
+-
+#
+GI: PROGRAMLISTINGCO
+# nothing to do specifically in ProgramListingCO -- it falls to
+# the content of ProgramListing and any callout list
+-
+#
+GI: SCREEN
+StartText: ^.PP^.nf^
+EndText: ^.fi^
+-
+#
+GI: SCREENCO
+# nothing to do specifically in ScreenCO -- it falls to
+# the content of Screen and any callout list
+-
+#
+GI: SCREENSHOT
+# nothing specific to do here -- defer to any ScreenInfo or the
+# included graphic
+-
+#
+GI: SCREENINFO
+StartText: ^.PP^\\fI
+EndText: \\fR^.PP^
+-
+#
+GI: GRAPHICCO
+# nothing to do specifically in GraphicCO -- it falls to
+# the content of Graphic and any callout list
+-
+#
+GI: INFORMALEXAMPLE
+# nothing special to do here -- it falls to the content.
+-
+#
+GI: EXAMPLE
+# nothing special to do here -- it falls to the content.
+-
+#
+GI: TITLE
+Context: EXAMPLE
+StartText: ^.PP^\\fB
+EndText: \\fR^
+-
+#
+GI: FIGURE
+# nothing special to do here -- it falls to the content.
+-
+#
+GI: TITLE
+Context: FIGURE
+StartText: ^.PP^\\fB
+EndText: \\fR^
+-
+#
+GI: SIDEBAR
+Relation: child TITLE
+StartText: ^.PP^.RS^
+EndText: ^.RE^
+-
+#
+GI: SIDEBAR
+StartText: ^.PP^.RS^\\fB[ Sidebar ]\\fR^
+EndText: ^.RE^
+-
+#
+GI: TITLE
+Context: SIDEBAR
+StartText: ^\\fB[ Sidebar:\s
+EndText: \s]\\fR^
+-
+#
+GI: HIGHLIGHTS
+StartText: ^.SS "Highlights"^
+-
+#
+GI: AUTHORBLURB
+# nothing to do specially -- an included title may occur
+-
+#
+GI: TITLE
+Context: AUTHORBLURB
+StartText: ^.PP^\\fB
+EndText: \\fR^
+-
+#
+#
+#############################################################################
+#
+# Call-out material
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: CO
+# nothing to do for the anchor of a callout
+-
+#
+GI: AREASPEC
+Ignore: all
+# not much to do with representing the anchor of callouts in n/troff
+-
+#
+GI: AREA
+Ignore: all
+# part of AreaSpec, which is being ignored
+-
+#
+GI: AREASET
+Ignore: all
+# part of AreaSpec, which is being ignored
+-
+#
+#
+#############################################################################
+#
+# Address block
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: ADDRESS
+StartText: ^.PP^.nf^
+EndText: ^.fi^
+-
+#
+GI: STREET
+# just the content...
+-
+#
+GI: POB
+# just the content...
+-
+#
+GI: POSTCODE
+# just the content...
+-
+#
+GI: CITY
+EndText: ,\s
+-
+#
+GI: STATE
+# just the content
+-
+#
+GI: COUNTRY
+# just the content
+-
+#
+GI: PHONE
+StartText: ^voice:\s
+-
+#
+GI: FAX
+StartText: ^fax:\s
+-
+#
+GI: OTHERADDR
+# just the content..
+-
+#
+GI: EMAIL
+Context: ADDRESS
+# just the content..
+-
+#
+#
+#############################################################################
+#
+# Lists
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: GLOSSLIST
+Relation: ancestor ITEMIZEDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: GLOSSLIST
+Relation: ancestor GLOSSLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: GLOSSLIST
+Relation: ancestor ORDEREDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: GLOSSLIST
+Relation: ancestor SIMPLELIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: GLOSSLIST
+Relation: ancestor VARIABLELIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: GLOSSLIST
+Relation: ancestor SEGMENTEDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: GLOSSLIST
+# Nothing to do here.. see glossentry, etc
+-
+#
+GI: GLOSSENTRY
+# nothing to do..
+-
+#
+GI: GLOSSTERM
+Context: GLOSSENTRY
+StartText: ^.IP "
+EndText: " 10^
+Substitute: " ""
+-
+#
+GI: GLOSSTERM
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: ACRONYM
+Context: GLOSSENTRY
+StartText: (\\fIacronym:\s\\fR
+EndText: )\s\s
+-
+#
+GI: ABBREV
+Context: GLOSSENTRY
+StartText: (\\fIabbreviation:\s\\fR
+EndText: )\s\s
+-
+#
+GI: GLOSSSEE
+StartText: ^\\fISee \\fR
+-
+#
+GI: GLOSSDEF
+# nothing special to do -- just pass the content.
+-
+#
+GI: GLOSSSEEALSO
+StartText: ^^\\fISee Also \\fR
+-
+#
+GI: ITEMIZEDLIST
+Relation: ancestor ITEMIZEDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: ITEMIZEDLIST
+Relation: ancestor GLOSSLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: ITEMIZEDLIST
+Relation: ancestor ORDEREDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: ITEMIZEDLIST
+Relation: ancestor SIMPLELIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: ITEMIZEDLIST
+Relation: ancestor VARIABLELIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: ITEMIZEDLIST
+Relation: ancestor SEGMENTEDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: ITEMIZEDLIST
+# nothing to do..
+-
+#
+GI: LISTITEM
+Context: ITEMIZEDLIST
+StartText: ^.IP "\ \ \ \\(bu" 6^
+-
+#
+GI: ORDEREDLIST
+Relation: ancestor ITEMIZEDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: ORDEREDLIST
+Relation: ancestor GLOSSLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: ORDEREDLIST
+Relation: ancestor ORDEREDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: ORDEREDLIST
+Relation: ancestor SIMPLELIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: ORDEREDLIST
+Relation: ancestor VARIABLELIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: ORDEREDLIST
+Relation: ancestor SEGMENTEDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: ORDEREDLIST
+StartText: ${_set orderlist 1}
+-
+#
+GI: LISTITEM
+Context: ORDEREDLIST
+StartText: ^.IP "\ \ \ ${orderlist}." 6^
+Increment: orderlist
+-
+#
+GI: SIMPLELIST
+Relation: ancestor ITEMIZEDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: SIMPLELIST
+Relation: ancestor GLOSSLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: SIMPLELIST
+Relation: ancestor ORDEREDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: SIMPLELIST
+Relation: ancestor SIMPLELIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: SIMPLELIST
+Relation: ancestor VARIABLELIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: SIMPLELIST
+Relation: ancestor SEGMENTEDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: SIMPLELIST
+# nothing to do here..
+-
+#
+GI: MEMBER
+PAttSet: TYPE INLINE
+NthChild: 1
+-
+#
+GI: MEMBER
+PAttSet: TYPE INLINE
+StartText: ,\s
+-
+#
+GI: MEMBER
+PAttSet: TYPE HORIZ
+NthChild: 1
+StartText: ^.PP^\t
+-
+#
+GI: MEMBER
+PAttSet: TYPE HORIZ
+StartText: \t
+-
+#
+GI: MEMBER
+PAttSet: TYPE VERT
+StartText: ^.IP "" 10^
+EndText: ^
+-
+#
+GI: VARIABLELIST
+Relation: ancestor ITEMIZEDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: VARIABLELIST
+Relation: ancestor GLOSSLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: VARIABLELIST
+Relation: ancestor ORDEREDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: VARIABLELIST
+Relation: ancestor SIMPLELIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: VARIABLELIST
+Relation: ancestor VARIABLELIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: VARIABLELIST
+Relation: ancestor SEGMENTEDLIST
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: VARIABLELIST
+# nothing to do now, see VarListEntry
+-
+#
+GI: VARLISTENTRY
+# nothing to do now, see Term
+-
+#
+GI: TERM
+StartText: ^.IP "
+EndText: " 10^
+Substitute: " ""
+-
+#
+GI: LISTITEM
+Context: VARLISTENTRY
+# nothing special to do..
+-
+#
+GI: SEGMENTEDLIST
+Relation: ancestor ITEMIZEDLIST
+StartText: ^.RS^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+EndText: ^.TE^.RE^
+-
+#
+GI: SEGMENTEDLIST
+Relation: ancestor GLOSSLIST
+StartText: ^.RS^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+EndText: ^.TE^.RE^
+-
+#
+GI: SEGMENTEDLIST
+Relation: ancestor ORDEREDLIST
+StartText: ^.RS^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+EndText: ^.TE^.RE^
+-
+#
+GI: SEGMENTEDLIST
+Relation: ancestor SIMPLELIST
+StartText: ^.RS^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+EndText: ^.TE^.RE^
+-
+#
+GI: SEGMENTEDLIST
+Relation: ancestor VARIABLELIST
+StartText: ^.RS^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+EndText: ^.TE^.RE^
+-
+#
+GI: SEGMENTEDLIST
+Relation: ancestor SEGMENTEDLIST
+StartText: ^.RS^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+EndText: ^.TE^.RE^
+-
+#
+GI: SEGMENTEDLIST
+Relation: child TITLE
+StartText: ^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+EndText: ^.TE^
+-
+#
+GI: TITLE
+Context: SEGMENTEDLIST
+# ignored by default -- must be called by SEGMENTEDLIST gi
+Ignore: all
+-
+#
+GI: _segmentedlist_title
+SpecID: 400
+StartText: ^.sp 1^\\fB
+EndText: \\fR^
+-
+#
+GI: SEGTITLE
+StartText: \\fB
+EndText: \\fR
+-
+#
+GI: SEGLISTITEM
+StartText: ^
+EndText: ^
+-
+#
+GI: SEG
+EndText: 
+-
+#
+GI: PROCEDURE
+# defer to the content...
+StartText: ${_set procstep 1}${_set procsubstep 1}
+-
+#
+GI: TITLE
+Context: PROCEDURE
+StartText: ^.PP^\\fB
+EndText: \\fR^
+-
+#
+GI: STEP
+Context: SUBSTEPS
+StartText: ^.PP^\\fISubstep ${procsubstep}.\s\s
+EndText: ^
+Increment: procsubstep 1
+-
+#
+GI: STEP
+StartText: ^.PP^\\fIStep ${procstep}.\s\s
+EndText: ^
+Increment: procstep 1
+-
+#
+GI: TITLE
+Context: STEP
+StartText: ^\\fB
+EndText: \\fR^.PP^
+-
+#
+GI: SUBSTEPS
+StartText: ^.RS^
+EndText: ^.RE^
+-
+#
+GI: CALLOUTLIST
+StartText: ${_set callout 1}
+# nothing to do specifically, defer to the content...
+-
+#
+GI: TITLE
+Context: CALLOUTLIST
+StartText: ^\\fB
+EndText: \\fR^.PP^
+-
+#
+GI: CALLOUT
+StartText: ^.PP^\\fICallout ${callout}.\s\s\\fR
+EndText: ^
+Increment: callout
+-
+#
+#
+#############################################################################
+#
+# Messages
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: MSGSET
+StartText: ^.SS "Message Set"^
+-
+#
+GI: MSGENTRY
+StartText: ^.PP^\\fBMessage Entry\\fR^.RS^
+EndText: ^.RE^
+-
+#
+GI: MSG
+Relation: child TITLE
+StartText: ^.PP^
+EndText: ^
+-
+#
+GI: MSG
+StartText: ^.PP^\\fBMessage:\\fR^.PP^
+EndText: ^
+-
+#
+GI: TITLE
+Context: MSG
+StartText: ^.PP^\\fB
+EndText: \\fR^.PP^
+-
+#
+GI: MSGINFO
+# nothing specific -- just groups (MsgLevel | MsgOrig | MsgAud)*
+-
+#
+GI: MSGEXPLAN
+# nothing special -- defer to content
+-
+#
+GI: TITLE
+Context: MSGEXPLAN
+StartText: ^.PP^\\fB
+EndText: \\fR^
+-
+#
+GI: MSGMAIN
+# defer to content
+-
+#
+GI: TITLE
+Context: MSGMAIN
+StartText: ^\\fB
+EndText: \\fR^
+-
+#
+GI: MSGSUB
+# defer to content
+-
+#
+GI: TITLE
+Context: MSGSUB
+StartText: ^.PP^\\fB
+EndText: \\fR^
+-
+#
+GI: MSGREL
+# defer to content
+-
+#
+GI: TITLE
+Context: MSGREL
+StartText: ^.PP^\\fB
+EndText: \\fR^
+-
+#
+GI: MSGLEVEL
+StartText: ^.PP^\\fIMessage level:\s\s\\fR
+EndText: ^
+-
+#
+GI: MSGORIG
+StartText: ^.PP^\\fIMessage origin:\s\s\\fR
+EndText: ^
+-
+#
+GI: MSGAUD
+StartText: ^.PP^\\fIMessage audience:\s\s\\fR
+EndText: ^
+-
+#
+GI: MSGTEXT
+Context: PARA
+StartText: \\fI
+EndText: \\fP
+-
+#
+GI: MSGTEXT
+StartText: \\fR^\\fIMessage text:\\fR\s\s
+EndText: ^
+-
+#
+#
+#############################################################################
+#
+# Admonitions
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: CAUTION
+Relation: child TITLE
+StartText: ^.PP^.RS
+EndText: ^.RE^
+-
+#
+GI: CAUTION
+StartText: ^.PP^.RS^\\fBCaution:\s\s
+EndText: ^.RE^
+-
+#
+GI: TITLE
+Context: CAUTION
+StartText: ^\\fBCaution:\s\s
+EndText: \\fR^.PP^
+-
+#
+GI: IMPORTANT
+Relation: child TITLE
+StartText: ^.PP^.RS^
+EndText: ^.RE^
+-
+#
+GI: IMPORTANT
+StartText: ^.PP^.RS^\\fBImportant:\s\s
+EndText: ^.RE^
+-
+#
+GI: TITLE
+Context: IMPORTANT
+StartText: ^\\fBImportant:\s\s
+EndText: \\fR^.PP^
+-
+#
+GI: NOTE
+Relation: child TITLE
+StartText: ^.PP^.RS
+EndText: ^.RE^
+-
+#
+GI: NOTE
+StartText: ^.PP^.RS^\\fBNote:\s\s
+EndText: ^.RE^
+-
+#
+GI: TITLE
+Context: NOTE
+StartText: ^\\fBNote:\s\s
+EndText: \\fR^.PP^
+-
+#
+GI: TIP
+Relation: child TITLE
+StartText: ^.PP^.RS
+EndText: ^.RE^
+-
+#
+GI: TIP
+StartText: ^.PP^.RS^\\fBTip:\s\s
+EndText: ^.RE^
+-
+#
+GI: TITLE
+Context: TIP
+StartText: ^\\fBTip:\s\s
+EndText: \\fR^.PP^
+-
+#
+GI: WARNING
+Relation: child TITLE
+StartText: ^.PP^.RS
+EndText: ^.RE^
+-
+#
+GI: WARNING
+StartText: ^.PP^.RS^\\fBWarning:\s\s
+EndText: ^.RE^
+-
+#
+GI: TITLE
+Context: WARNING
+StartText: ^\\fBWarning:\s\s
+EndText: \\fR^.PP^
+-
+#
+#
+#############################################################################
+#
+# Synopses
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: SYNOPSIS
+StartText: ^.PP^.nf^
+EndText: ^.fi^
+-
+#
+GI: CMDSYNOPSIS
+StartText: ^.PP^
+EndText: ^
+-
+#
+GI: ARG
+Context: GROUP
+NthChild: 1
+EndText: ${_attval REP REPEAT 505}\s
+-
+#
+GI: ARG
+Context: GROUP
+StartText: \s|\s
+EndText: ${_attval REP REPEAT 505}\s
+-
+#
+GI: ARG
+AttValue: CHOICE OPT
+StartText: \s[
+EndText: ${_attval REP REPEAT 505}]\s
+-
+#
+GI: ARG
+# no special attrs -- just pass content through
+EndText: ${_attval REP REPEAT 505}\s
+-
+#
+GI: _arg_group
+SpecID: 505
+StartText: \s\\&...
+Ignore: all
+-
+#
+GI: GROUP
+AttValue: CHOICE OPT
+StartText: \s[
+EndText: ]\s${_attval REP REPEAT 505}
+-
+#
+GI: GROUP
+AttValue: CHOICE REQ
+StartText: \s{
+EndText: }\s${_attval REP REPEAT 505}
+-
+#
+GI: GROUP
+AttValue: CHOICE OPTMULT
+StartText: \s[[
+EndText: ]]\s${_attval REP REPEAT 505}
+-
+#
+GI: GROUP
+AttValue: CHOICE REQMULT
+StartText: \s{{
+EndText: }}\s${_attval REP REPEAT 505}
+-
+#
+GI: GROUP
+AttValue: CHOICE PLAIN
+EndText: ${_attval REP REPEAT 505}
+-
+#
+GI: SBR
+StartText: ^.br^
+-
+#
+GI: SYNOPFRAGMENT
+# nothing special to do here -- just pass through content (Arg | Group)+
+-
+#
+GI: SYNOPFRAGMENTREF
+# WHAT TO DO HERE?? pass through the content, but what about the
+# linkend? (will call it across...)
+EndText: \s\\fI(refers to: ${_followlink LINKEND 1000})\\fR
+-
+#
+GI: FUNCSYNOPSIS
+StartText: ^.PP^.nf^
+EndText: ^.fi^
+-
+#
+GI: FUNCSYNOPSISINFO
+StartText: ^
+EndText: ^
+-
+#
+GI: FUNCPROTOTYPE
+# nothing special -- just pass through content (looks like
+# a function def
+StartText: ^.sp 1^
+-
+#
+GI: FUNCDEF
+StartText: ^\\fB
+EndText: \\fR(
+-
+#
+GI: FUNCPARAMS
+StartText: ^\t\t\t\\fB
+EndText: \\fR^
+-
+#
+GI: VOID
+StartText: \\fBvoid\\fR);
+-
+#
+GI: VARARGS
+StartText: \\fB\\&...\\fR);
+-
+#
+GI: PARAMDEF
+Relation: sibling+ PARAMDEF
+StartText: ^\\fB
+EndText: \\fR,^
+-
+#
+GI: PARAMDEF
+StartText: ^\\fB
+EndText: \\fR);^
+-
+#
+#
+#############################################################################
+#
+# Links
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: LINK
+StartText: \\fI
+EndText: \\fR
+-
+#
+GI: OLINK
+StartText: \\fI
+EndText: \s(link to external document ${TargetDocEnt})\s\\fR
+-
+#
+GI: ULINK
+StartText: \\fI
+EndText: \s(link to URL ${URL})\s\\fR
+-
+#
+GI: FOOTNOTEREF
+# just let the footnote ref mark come through
+-
+#
+GI: FOOTNOTE
+# just let footnote body come through (-man doesn't support footnotes)
+-
+#
+GI: XREF
+AttValue: ENDTERM
+StartText: \\fI(cross-reference to ``${_followlink ENDTERM 1000}'')\\fR\s
+-
+#
+GI: XREF
+StartText: \\fI(cross-reference to ``${_followlink LINKEND 600})''\\fR\s
+-
+#
+GI: _xref
+SpecID: 600
+StartText: ${XREFLABEL}
+Ignore: all
+-
+#
+GI: ANCHOR
+# nothing to do -- this just marks a place..
+-
+#
+#
+#############################################################################
+#
+# Graphics and Equations
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: GRAPHIC
+AttValue: ENTITYREF
+StartText: ^.PP^.if t .P! "${_filename}"^
+-
+#
+GI: INLINEGRAPHIC
+StartText: ^.if t .P! "${_filename}"^
+-
+#
+GI: INFORMALEQUATION
+# nothing special to do -- defer to graphic content..
+-
+#
+GI: EQUATION
+# nothing special to do -- defer to graphic content..
+-
+#
+GI: TITLE
+Context: EQUATION
+StartText: ^.PP^\\fB
+EndText: \\fR^
+-
+#
+GI: INLINEEQUATION
+# nothing special to do -- defer to graphic content..
+-
+#
+#
+#############################################################################
+#
+# Tables
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+#
+GI: INFORMALTABLE
+StartText: ^${_calstable tbl tablestart}^
+EndText: ^${_calstable tbl tableend}^
+-
+#
+GI: TABLE
+StartText: ^.PP^\\fB${_followrel child TITLE 1000}\\fR
+ ^${_calstable tbl tablestart}^
+EndText: ^${_calstable tbl tableend}^
+-
+#
+GI: TITLE
+Context: TABLE
+# handled in TABLE element
+Ignore: all
+-
+#
+GI: TGROUP
+StartText: ^${_calstable tbl tablegroup}^${_followrel child THEAD 700}${_followrel child TBODY 700}${_followrel child TFOOT 701}
+EndText: ${_calstable tbl tablegroupend}
+-
+#
+GI: COLSPEC
+Ignore: all
+-
+#
+GI: SPANSPEC
+Ignore: all
+-
+#
+GI: THEAD TBODY TFOOT
+# they're called explicitly from TGROUP, but ignored here
+Ignore: all
+-
+#
+GI: _thead_tbody
+SpecID: 700
+# nothing special to do -- just pass through content
+-
+#
+GI: _tfoot
+SpecID: 701
+StartText: ^${_calstable tbl tablefoot}^
+-
+#
+GI: ROW
+StartText: ^${_calstable tbl rowstart}
+EndText: ${_calstable tbl rowend}
+-
+#
+GI: ENTRY
+StartText: ${_calstable tbl entrystart}
+EndText: ${_calstable tbl entryend}
+-
+#
+GI: ENTRYTBL
+StartText:
+EndText:
+Message: ^IMPLEMENT <${_gi} ${_allatts}>^
+-
+#
+#
+#############################################################################
+#
+# Index terms
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: INDEXTERM
+StartText: ^.iX\s
+EndText: ^
+-
+#
+GI: PRIMARY
+StartText: "
+EndText: "
+-
+#
+GI: SECONDARY
+StartText: \s"
+EndText: "
+-
+#
+GI: TERTIARY
+StartText: \s"
+EndText: "
+-
+#
+GI: SEE
+StartText: \s"See:\s
+EndText: "
+-
+#
+GI: SEEALSO
+StartText: \s"SeeAlso:\s
+EndText: "
+-
+#
+#
+#############################################################################
+#
+# Author / OtherCredit material
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: OTHERCREDIT
+# nothing specific -- defer to content
+-
+#
+GI: HONORIFIC
+# nothing specific -- defer to content
+EndText: \s
+-
+#
+GI: FIRSTNAME
+# nothing specific -- defer to content
+EndText: \s
+-
+#
+GI: SURNAME
+# nothing specific -- defer to content
+EndText: \s
+-
+#
+GI: LINEAGE
+# nothing specific -- defer to content
+EndText: \s
+-
+#
+GI: OTHERNAME
+# nothing specific -- defer to content
+StartText: (
+EndText: )\s
+-
+#
+GI: AFFILIATION
+# nothing specific -- defer to content
+EndText: \s
+-
+#
+GI: SHORTAFFIL
+# nothing specific -- defer to content
+EndText: \s
+-
+#
+GI: JOBTITLE
+# nothing specific -- defer to content
+EndText: \s
+-
+#
+GI: ORGNAME
+# nothing specific -- defer to content
+EndText: \s
+-
+#
+GI: ORGDIV
+# nothing specific -- defer to content
+EndText: \s
+-
+#
+GI: CONTRIB
+# nothing specific -- defer to content
+EndText: \s
+-
+#
+#
+#############################################################################
+#
+# "Leaf" material
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: ABBREV
+# no special presentation
+-
+#
+GI: ACCEL
+# no special presentation
+-
+#
+GI: ACRONYM
+# no special presentation
+-
+#
+GI: AUTHORINITIALS
+# no special presentation
+-
+#
+GI: CITATION
+StartText: \\fI
+EndText: \\fP
+-
+#
+GI: CITETITLE
+AttValue: PUBWORK
+StartText: \\fI
+EndText: \\fP (${PUBWORK})\s
+-
+#
+GI: CITETITLE
+StartText: \\fI
+EndText: \\fP
+-
+#
+GI: CITEREFENTRY
+# defer to content..
+-
+#
+GI: REFENTRYTITLE
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: MANVOLNUM
+StartText: \\fB(
+EndText: )\\fP
+-
+#
+GI: COMMENT
+# docbook says to inhibit this from finished products...
+Ignore: all
+-
+#
+GI: EMAIL
+# no special presentation
+-
+#
+GI: EMPHASIS
+StartText: \\fI
+EndText: \\fP
+-
+#
+GI: FIRSTTERM
+StartText: \\fI
+EndText: \\fR
+-
+#
+GI: FOREIGNPHRASE
+# no special presentation
+-
+#
+GI: PHRASE
+# no special presentation
+-
+#
+GI: QUOTE
+StartText: ``\\fI
+EndText: \\fP''
+-
+#
+GI: TRADEMARK
+EndText: \\u\\s-2TM\\s+2\\d
+-
+#
+GI: WORDASWORD
+# no special presentation
+-
+#
+GI: ACTION
+# no special presentation
+-
+#
+GI: APPLICATION
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: CLASSNAME
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: COMMAND
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: COMPUTEROUTPUT
+StartText: \\f(CW
+EndText: \\fP
+-
+#
+GI: DATABASE
+# no special presentation
+-
+#
+GI: ERRORNAME
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: ERRORTYPE
+# no special presentation
+-
+#
+GI: FILENAME
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: FUNCTION
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: GUIBUTTON
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: GUIICON
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: GUILABEL
+# no special presentation
+-
+#
+GI: GUIMENU
+# no special presentation
+-
+#
+GI: GUIMENUITEM
+# no special presentation
+-
+#
+GI: GUISUBMENU
+# no special presentation
+-
+#
+GI: HARDWARE
+# no special presentation
+-
+#
+GI: INTERFACE
+# no special presentation
+-
+#
+GI: INTERFACEDEFINITION
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: KEYCAP
+StartText: \\fB<
+EndText: >\\fP
+-
+#
+GI: KEYCODE
+# no special presentation
+-
+#
+GI: KEYCOMBO
+# no special presentation -- defer to the content
+-
+#
+GI: KEYSYM
+StartText: \\fB<
+EndText: >\\fP
+-
+#
+GI: LINEANNOTATION
+StartText: \\fI
+EndText: \\fP
+-
+#
+GI: LITERAL
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: MARKUP
+StartText: \\f(CW
+EndText: \\fP
+-
+#
+GI: MEDIALABEL
+# no special presentation
+-
+#
+GI: MENUCHOICE
+# no special presentation
+-
+#
+GI: SHORTCUT
+# no special presentation
+-
+#
+GI: MOUSEBUTTON
+# no special presentation
+-
+#
+GI: OPTION
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: OPTIONAL
+StartText: [
+EndText: ]
+-
+#
+GI: PARAMETER
+StartText: \\fB
+EndText: \\fR
+-
+#
+GI: PROPERTY
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: REPLACEABLE
+StartText: \\fI
+EndText: \\fP
+-
+#
+GI: RETURNVALUE
+StartText: \\fB
+EndText: \\fR
+-
+#
+GI: SGMLTAG
+AttValue: CLASS ELEMENT
+StartText: \\fB<
+EndText: >\\fP
+-
+#
+GI: SGMLTAG
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: STRUCTFIELD
+StartText: \\fB
+EndText: \\fR
+-
+#
+GI: STRUCTNAME
+StartText: \\fB
+EndText: \\fR
+-
+#
+GI: SYMBOL
+AttValue: ROLE Variable
+StartText: \\fI
+EndText: \\fP
+-
+#
+GI: SYMBOL
+StartText: \\fI
+EndText: \\fP
+-
+#
+GI: SYSTEMITEM
+AttValue: CLASS CONSTANT
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: SYSTEMITEM
+AttValue: CLASS ENVIRONVAR
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: SYSTEMITEM
+AttValue: CLASS RESOURCE
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: SYSTEMITEM
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: TOKEN
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: TYPE
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: USERINPUT
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: AUTHOR
+# no special presentation - defer to content
+-
+#
+GI: CORPAUTHOR
+# no special presentation
+-
+#
+GI: MODESPEC
+# nothing to render (this is meta information for Links)
+-
+#
+GI: PRODUCTNAME
+StartText: \\fB
+EndText: \\fP
+-
+#
+GI: PRODUCTNUMBER
+# no special presentation
+-
+#
+GI: SUBSCRIPT
+StartText: \\d
+EndText: \\u
+-
+#
+GI: SUPERSCRIPT
+StartText: \\u
+EndText: \\d
+-
+#
+#
+#############################################################################
+#
+# stuff that gets ignored (and doesn't belong elsewhere)
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: TITLEABBREV
+# this element is ignored in favor of the real title
+Ignore: all
+-
+#
+#
+#
+#############################################################################
+#
+# handle layout-specific stuff and PIs
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: BEGINPAGE
+StartText: ^.br\s
+EndText: ^
+-
+#
+GI: _x-break
+StartText: ^.br\s
+EndText: ^
+-
+#
+GI: _sml-break
+StartText: ^.br\s
+EndText: ^
+-
+#
+GI: _sml-need
+StartText: ^.ne\s
+EndText: ^
+-
+#
+GI: _sml-size
+StartText: ^.ps\s
+EndText: ^
+-
+#
+GI: _sml-indent
+StartText: ^.in\s
+EndText: ^
+-
+#
+GI: _sml-space
+StartText: ^.sp\s
+EndText: ^
+-
+#
+GI: _sml-tabset
+StartText: ^.ta\s
+EndText: ^
+-
+#
+#
+#############################################################################
+#
+# General purpose transpecs
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: _passthrough
+SpecID: 1000
+-
+#
+GI: _passthrough2
+SpecID: 1001
+StartText: ${+caps}
+Ignore: all
+-
+#
+GI: _doTitle
+SpecID: 1010
+StartText: ^.PP^\\fB
+EndText: \\fR^.PP^
+-
+#
+#
+#############################################################################
+#
+# Catch-all for unknown PIs -- ignore them...
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+GI: _*
+Ignore: data
+-
+#
+#
+#############################################################################
+#
+# Catch-all for unknown elements -- just output their content..
+#
+# #### ##### ##### ##### ##### ##### #### #####
+#
+#GI: *
+#-
+#
diff --git a/doc/README b/doc/README
new file mode 100644
index 0000000..e153b81
--- /dev/null
+++ b/doc/README
@@ -0,0 +1,26 @@
+
+FILES
+=====
+
+authors.txt
+ notes for authors of the GTK documentation. The abbreviations to use,
+ a few useful DocBook tabs etc.
+
+notes.txt
+ my initial thoughts on the documentation - what should be included,
+ other documentation to look at etc.
+
+gtk_button.txt
+ the man page written by Shawn Admundson. I've tried to
+ copy the structure as much as possible.
+
+gnome.txt
+ information on the source code comments format which the Gnome project
+ has just started to use.
+
+manpage
+ a man page in DocBook format which I found in the DocBook documentation.
+
+manpage.man
+ the above man page converted with docbook-to-man. View with 'man -l'.
+
diff --git a/doc/authors.txt b/doc/authors.txt
new file mode 100644
index 0000000..24dacd2
--- /dev/null
+++ b/doc/authors.txt
@@ -0,0 +1,174 @@
+Tools
+=====
+
+* gtkdoc-scan
+
+ Scan a set of header files for declarations.
+
+ Usage: gtkdoc-scan --module=MODULE [--output-dir=DIR] FILES
+
+* gtkdoc-scanobj
+
+ Compile a C program to get information about GTK+ objects.
+
+ Usage: gtkdoc-scan --module=MODULE
+
+* gtkdoc-mktmpl
+
+ Make template files from declaration files
+
+ Usage: gtkdoc-mkhtml --module=MODULE
+
+* gtkdoc-mkdb
+
+ Make DocBook output from declaration files and template files.
+
+ Usage: gtkdoc-mkdb --module=MODULE
+
+* gtkdoc-mkhtml
+
+ Usage: gtkdoc-mkhtml MODULE DRIVER_FILE
+
+* gtkdoc-mkman
+
+ Usage: gtkdoc-mkman
+
+General
+=======
+
+The files to edit manually are in the gtkdocs directory, and are split into 3
+subdirectories for glib, gdk and gtk.
+
+You may find useful information in the GTK tutorial, or the info documentation.
+
+
+You must use &lt; or &gt; instead of '<' and '>'.
+
+The first part of each function/macro/struct etc. description should be
+a very short summary of what it is. This may be used at some point to
+produce a short reference guide which can be printed out.
+
+For macros which return a value just like a function, you must manually
+add a '@Returns: ' field.
+
+You may want to rearrange the functions/macros etc. to split them into
+related sections. To do this rearrange the scan-gtk-perl/gXXX-sections.txt
+files. You can also add <SUBSECTION> between functions. Currently this just
+results in a blank line between them in the synopsis.
+
+
+Abbreviations
+=============
+
+These are expanded into appropriate DocBook tags, saving a lot of typing.
+I've used the Gnome ones (see gnome.txt) but also added '#'.
+
+ Use function() to refer to functions or macros which take arguments.
+
+ Use @param to refer to parameters. (I've also used this when referring to
+ parameters of other functions, related to the one being described.)
+
+ Use %constant to refer to a constant, e.g. %G_TRAVERSE_LEAFS.
+
+ Use #symbol to refer to other types of symbol, e.g. structs and enums
+ and macros which don't take arguments.
+
+
+
+Useful DocBook Tags
+===================
+
+These are the DocBook tags which I have used or I think could be useful.
+Let me know if I'm doing something wrong!
+
+
+To link to another section in the GTK docs:
+
+ <link linkend="glib-Hash-Tables">Hash Tables</link>
+
+ The linkend is the SGML id on the top item of the page you want to link to.
+ For most pages this is currently the part ("gtk", "gdk", glib") and then
+ the page title ("Hash Tables"). For widgets it is just the class name.
+ Spaces and underscores are converted to '-' to conform to SGML.
+
+
+To refer to an external function, e.g. a standard C function:
+
+ <function>...</function>
+
+
+To include example code:
+
+ <example>
+ <title>Using a Hash Table</title>
+ <programlisting>
+ ...
+ </programlisting>
+ </example>
+
+ or possibly:
+
+ <informalexample>
+ <programlisting>
+ ...
+ </programlisting>
+ </informalexample>
+
+
+To include bulleted lists:
+
+ <itemizedlist>
+ <listitem><para>
+ ...
+ </para></listitem>
+ <listitem><para>
+ ...
+ </para></listitem>
+ ....
+ </itemizedlist>
+
+
+To include a note which stands out from the text:
+
+ <note>
+ <para>
+ Make sure you free the data after use.
+ </para>
+ </note>
+
+To refer to a type:
+
+ <type>unsigned char</type>
+
+
+To refer to an external structure (not one described in the GTK docs):
+
+ <structname>XFontStruct</structname>
+
+
+To refer to a field of a structure:
+
+ <structfield>len</structfield>
+
+
+To refer to a class name, we could possibly use:
+
+ <classname>GtkWidget</classname>
+
+ but you'll probably be using #GtkWidget instead (to automatically create
+ a link to the GtkWidget page - see the abbreviations above).
+
+
+To emphasize text:
+
+ <emphasis>This is important</emphasis>
+
+ but I haven't been using it so far.
+
+
+For filenames use:
+
+ <filename>c:\windows</filename>
+
+
+Also, <screenshot>, <option>, \ No newline at end of file
diff --git a/doc/gnome.txt b/doc/gnome.txt
new file mode 100644
index 0000000..e3d5364
--- /dev/null
+++ b/doc/gnome.txt
@@ -0,0 +1,79 @@
+From: Miguel de Icaza [miguel@nuclecu.unam.mx]
+Sent: 16 October 1998 00:13
+To: dusk@smsi-roman.com
+Cc: rosalia@cygnus.com; gnome-list@gnome.org
+Subject: Re: Documentation
+
+
+> When was this? Was it on gnome-list? (And where was I? :c) I've
+> scanned the past couple months, and can't find either proposal. I vaguely
+> remember the embedded C comment thread, but nothing official about it.
+
+here is the document:
+
+------------------ api-commenting-style.txt --------------------
+
+I suggest we use the following to documenting API entry points in the
+GNOME libraries. I have written a simple Perl script that can extract
+these comments into a file. I will need to make my Perl script
+generate DocBook output.
+
+/**
+ * function_name:
+ * @par1: description of parameter 1
+ * @par2: description of parameter 2
+ *
+ * function description. You can include references to parameters
+ * here like @par1 and their font will be set properly on the output.
+ * constants can be references with %constant as well to make their
+ * string descriptions use a font specification. This function
+ * is simliar to #function_name2 in this and that
+ *
+ * return values: an integer.
+ */
+int
+function_name (int par1, char * par2)
+{
+}
+
+The important parts are:
+
+The first line of an API entry point documentation starts with /**
+like the Java documentation system (slash and two stars). The comment
+is formatted with stars at the beginning of each line. The second
+line is the function name, it might include an optional ':' for beautification
+purposes.
+
+A number of keywords can be included in the function_name line, so far
+only the [constructor] string has a special meaning (it is used to
+list before any other API entry points in the generated output). We
+can define more of those attributes in the future.
+
+Any line from that point on that matches the regular expression:
+
+ ^ \* @[a-zA-Z0-9]:
+
+(for example: " * @par1: parameter one")
+
+Is taken to be the declaration of a function parameter. We can
+extract the type of this parameter from the actual function definition.
+
+After the parameters we have the function description. If any line of
+the function description matches the regexp:
+
+ ^ \* [Rr]eturn
+
+It is taken to be the description of the return value for the
+function.
+
+Text inside the descritpion can have any of the following special tags
+on the beginning:
+
+ @name: reference to a parameter.
+ %name: reference to a constant.
+ name(): function reference.
+
+
+--
+ To unsubscribe: mail gnome-list-request@gnome.org with
+ "unsubscribe" as the Subject.
diff --git a/doc/gtk_button.txt b/doc/gtk_button.txt
new file mode 100644
index 0000000..24a2b3e
--- /dev/null
+++ b/doc/gtk_button.txt
@@ -0,0 +1,235 @@
+NAME
+ gtk_button - GTK+ push button widget
+
+SYNOPSIS
+ #include <gtk/gtkbutton.h>
+
+ GtkType gtk_button_get_type (void);
+ GtkWidget* gtk_button_new (void);
+ GtkWidget* gtk_button_new_with_label (const gchar *label);
+ void gtk_button_pressed (GtkButton *button);
+ void gtk_button_released (GtkButton *button);
+ void gtk_button_clicked (GtkButton *button);
+ void gtk_button_enter (GtkButton *button);
+ void gtk_button_leave (GtkButton *button);
+ void gtk_button_set_relief (GtkButton *button,
+ GtkReliefStyle style);
+ GtkReliefStyle gtk_button_get_relief (GtkButton *button);
+
+DESCRIPTION
+ This widget is a standard push button widget. Push button
+ widgets are generally used for allowing the user to click on
+ them to initiate a command.
+
+ This widget is a container widget which contains one child.
+
+OBJECT HIERARCHY
+ gtk_object
+ gtk_widget
+ gtk_container
+ gtk_button
+
+SIGNAL PROTOTYPES
+ "clicked" void user_function (GtkWidget *widget, gpointer data);
+ "pressed" void user_function (GtkWidget *widget, gpointer data);
+ "released" void user_function (GtkWidget *widget, gpointer data);
+ "enter" void user_function (GtkWidget *widget, gpointer data);
+ "leave" void user_function (GtkWidget *widget, gpointer data);
+
+USAGE
+ Creation
+
+ The most common way to create a button is with a label in it,
+ which contains text for the user to read. The child of the
+ button will then be a the gtk_label(3) manpage widget with the
+ text you passwd in. You can do this in one command:
+
+ GtkWidget *button;
+ button = gtk_button_new_with_label ("This is a button");
+
+ To create a gtk_button widget which does not already have a
+ child, use gtk_button_new():
+
+ GtkWidget *button;
+ button = gtk_button_new ();
+
+ After you have created a button you can then add a widget to the
+ button (such as a label or pixmap) using gtk_container_add().
+ See the gtk_container(3) manpage for more information on adding
+ widgets to containers.
+
+ Creating a pixmap in a button in a window
+
+ After we have an empty gtk_button, such as above, and we have a
+ gtk_pixmap, we can simply add the gtk_pixmap to the gtk_button
+ with gtk_container_add().
+
+ The following code will open the file "gimp.xpm" and place it in
+ a button.
+
+ #include <gtk/gtk.h>
+
+ int main (int argc, char *argv[])
+ {
+ GtkWidget *window;
+ GtkWidget *button;
+ GtkWidget *pixmap;
+ GtkStyle *style;
+ GdkPixmap *gdkpixmap;
+ GdkBitmap *mask;
+ char *filename = "gimp.xpm";
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ button = gtk_button_new ();
+ gtk_container_add (GTK_CONTAINER (window), button);
+
+ /* The button is realized now, which creates button->window
+ used below to create the pixmap. */
+ gtk_widget_realize (button);
+
+ style = gtk_widget_get_style (button);
+ gdkpixmap = gdk_pixmap_create_from_xpm (button->window, &mask,
+ &style->bg[GTK_STATE_NORMAL],
+ filename);
+ pixmap = gtk_pixmap_new (gdkpixmap, mask);
+
+ gtk_container_add (GTK_CONTAINER (button), pixmap);
+
+ gtk_widget_show (pixmap);
+ gtk_widget_show (button);
+ gtk_widget_show (window);
+
+ gtk_main ();
+ return 0;
+ }
+
+ Different reliefs
+
+ Reliefs affect how the shadowing of the button is drawn. The
+ different types of relief styles are:
+
+ GTK_RELIEF_NORMAL
+ GTK_RELIEF_HALF
+ GTK_RELIEF_NONE
+
+ When set to a normal relief, the widget looks and acts like a
+ normal button. When half or none relief is used, shadowing is
+ only drawn when the mouse cursor is over the widget.
+
+ To set the relief, use gtk_button_set_relief(), like:
+
+ gtk_button_set_relief (button, GTK_RELIEF_HALF);
+
+ To get the current relief of a button, use
+ gtk_button_get_relief():
+
+ GtkReliefStyle relief;
+ relief = gtk_button_get_relief (GTK_BUTTON (button));
+
+ Executing a command when the button is pressed
+
+ To execute a function when a button is pressed, use
+ gtk_signal_connect() to connect to the "clicked" signal.
+
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (user_function),
+ NULL);
+
+ user_function is a user defined function, like the following:
+
+ void user_function (GtkWidget *button, gpointer data)
+ {
+ printf("clicked\n");
+ }
+
+FUNCTIONS
+ GtkType gtk_button_get_type (void);
+
+ This function returns the GtkType which is assigned to the
+ object class for gtk_button.
+
+ GtkWidget* gtk_button_new (void);
+
+ This functions returns a new button widget which can then be
+ used as a container for another widget.
+
+ GtkWidget* gtk_button_new_with_label (const gchar *label);
+
+ This function returns a new button widget with a label widget
+ as a child. The label widget will have the text passed into
+ the commant.
+
+ void gtk_button_pressed (GtkButton *button);
+
+ This function sends a "pressed" signal to the button.
+
+ void gtk_button_released (GtkButton *button);
+
+ This function sends a "released" signal to the button.
+
+ void gtk_button_clicked (GtkButton *button);
+
+ This function sends a "clicked" signal to the button.
+
+ void gtk_button_enter (GtkButton *button);
+
+ This function sends a "enter" signal to the button.
+
+ void gtk_button_leave (GtkButton *button);
+
+ This function sends a "leave" signal to the button.
+
+ void gtk_button_set_relief (GtkButton *button, GtkReliefStyle
+ style);
+
+ This function is sets the GtkReliefStyle of the button. The
+ relief style is one of: GTK_RELIEF_NORMAL, GTK_RELIEF_HALF,
+ or GTK_RELIEF_NONE. The relief determines when the shadow of
+ the button is drawn.
+
+ GtkReliefStyle gtk_button_get_relief (GtkButton *button);
+
+ This function returns the current relief of the button.
+
+SIGNALS
+ "clicked"
+
+ void user_function (GtkWidget *widget, gpointer data);
+
+ Gets emitted when the button is clicked. A click is
+ a press and release of the button when the cursor is
+ inside the button on release.
+
+ "pressed"
+
+ void user_function (GtkWidget *widget, gpointer data);
+
+ Gets emitted when the left mouse button is pressed.
+
+ "released"
+
+ void user_function (GtkWidget *widget, gpointer data);
+
+ Gets emitted when the left mouse button is released and
+ the widget was previously pressed.
+
+ "enter"
+
+ void user_function (GtkWidget *widget, gpointer data);
+
+ Emitted when the mouse cursor enters the button.
+
+ "leave"
+
+ void user_function (GtkWidget *widget, gpointer data);
+
+ Emitted when the mouse cursor leaves the button.
+
+AUTHORS
+ The author of this man page is Shawn T. Amundson
+ <amundson@gtk.org>. For the authors of GTK+, see the AUTHORS
+ file in the GTK+ distribution.
+
diff --git a/doc/manpage b/doc/manpage
new file mode 100644
index 0000000..6cd98a6
--- /dev/null
+++ b/doc/manpage
@@ -0,0 +1,170 @@
+<!doctype refentry PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
+<REFENTRY ID="RE-1007-UNMANAGECHILDREN-1">
+
+<REFMETA>
+<REFENTRYTITLE>XtUnmanageChildren</REFENTRYTITLE>
+<MANVOLNUM>3
+<REFMISCINFO>Xt - Geometry Management</REFMISCINFO>
+</REFMETA>
+
+
+<REFNAMEDIV>
+<REFNAME>XtUnmanageChildren
+</REFNAME>
+<REFPURPOSE>remove a list of children from a parent widget's managed list.
+</REFPURPOSE>
+<INDEXTERM ID="IX-1007-UNMANAGECHILDREN-1"><PRIMARY>widgets</PRIMARY><SECONDARY>removing</SECONDARY></INDEXTERM>
+<INDEXTERM ID="IX-1007-UNMANAGECHILDREN-2"><PRIMARY>XtUnmanageChildren</PRIMARY></INDEXTERM>
+</REFNAMEDIV>
+
+
+<REFSYNOPSISDIV>
+<REFSYNOPSISDIVINFO>
+<DATE>4 March 1996</DATE>
+</REFSYNOPSISDIVINFO>
+<SYNOPSIS>
+void XtUnmanageChildren(<REPLACEABLE CLASS="PARAMETER">children</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">num_children</REPLACEABLE>)
+ WidgetList <REPLACEABLE CLASS="PARAMETER">children</REPLACEABLE>;
+ Cardinal <REPLACEABLE CLASS="PARAMETER">num_children</REPLACEABLE>;</SYNOPSIS>
+
+<REFSECT2 ID="R2-1007-UNMANAGECHILDREN-1">
+<REFSECT2INFO>
+<DATE>6 March 1996</DATE>
+</REFSECT2INFO>
+<TITLE>Inputs
+</TITLE>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM><REPLACEABLE CLASS="PARAMETER">children</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies an array of child widgets. Each child must be of
+class RectObj or any subclass thereof.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM><REPLACEABLE CLASS="PARAMETER">num_children</REPLACEABLE>
+</TERM>
+<LISTITEM>
+<PARA>Specifies the number of elements in <REPLACEABLE CLASS="PARAMETER">children</REPLACEABLE>.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+<REFSECT3>
+<TITLE>Subsidiary Inputs</TITLE>
+<PARA>Inputs into unmanageable children may also include
+food, drink, and discipline.
+</PARA>
+</REFSECT3>
+</REFSECT2></REFSYNOPSISDIV>
+
+
+<REFSECT1 ID="R1-1007-UNMANAGECHILDREN-1">
+<REFSECT1INFO>
+<DATE>5 March 1996</DATE>
+</REFSECT1INFO>
+<TITLE>Description
+</TITLE>
+<PARA><FUNCTION>XtUnmanageChildren()</FUNCTION> unmaps the specified widgets
+and removes them from their parent's geometry management.
+The widgets will disappear from the screen, and (depending
+on its parent) may no longer have screen space allocated for
+them.
+</PARA>
+<PARA>Each of the widgets in the <REPLACEABLE CLASS="PARAMETER">children</REPLACEABLE> array must have
+the same parent.
+</PARA>
+<PARA>See the &ldquo;Algorithm&rdquo; section below for full details of the
+widget unmanagement procedure.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-1007-UNMANAGECHILDREN-2">
+<TITLE>Usage
+</TITLE>
+<PARA>Unmanaging widgets is the usual method for temporarily
+making them invisible. They can be re-managed with
+<FUNCTION>XtManageChildren()</FUNCTION>.
+</PARA>
+<PARA>You can unmap a widget, but leave it under geometry
+management by calling <FUNCTION>XtUnmapWidget()</FUNCTION>. You can
+destroy a widget's window without destroying the widget by
+calling <FUNCTION>XtUnrealizeWidget()</FUNCTION>. You can destroy a
+widget completely with <FUNCTION>XtDestroyWidget()</FUNCTION>.
+</PARA>
+<PARA>If you are only going to unmanage a single widget, it is
+more convenient to call <FUNCTION>XtUnmanageChild()</FUNCTION>. It is
+often more convenient to call <FUNCTION>XtUnmanageChild()</FUNCTION>
+several times than it is to declare and initialize an array
+of widgets to pass to <FUNCTION>XtUnmanageChildren()</FUNCTION>. Calling
+<FUNCTION>XtUnmanageChildren()</FUNCTION> is more efficient, however,
+because it only calls the parent's <FUNCTION>change_managed()</FUNCTION>
+method once.
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-1007-UNMANAGECHILDREN-3">
+<TITLE>Algorithm
+</TITLE>
+<PARA><FUNCTION>XtUnmanageChildren()</FUNCTION> performs the following:
+</PARA>
+<VARIABLELIST>
+<VARLISTENTRY>
+<TERM>&bull;
+</TERM>
+<LISTITEM>
+<PARA>Issues an error if the children do not all have the same
+parent or if the parent is not a subclass of
+<CLASSNAME>compositeWidgetClass</CLASSNAME>.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>&bull;
+</TERM>
+<LISTITEM>
+<PARA>Returns immediately if the common parent is being destroyed;
+otherwise, for each unique child on the list,
+<FUNCTION>XtUnmanageChildren()</FUNCTION> performs the following:
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>-
+</TERM>
+<LISTITEM>
+<PARA>Ignores the child if it already is unmanaged or is being
+destroyed.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>-
+</TERM>
+<LISTITEM>
+<PARA>Otherwise, if the child is realized, it makes it nonvisible
+by unmapping it.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+<VARLISTENTRY>
+<TERM>&bull;
+</TERM>
+<LISTITEM>
+<PARA>Calls the <FUNCTION>change_managed()</FUNCTION> method of the widgets'
+parent if the parent is realized.
+</PARA>
+</LISTITEM>
+</VARLISTENTRY>
+</VARIABLELIST>
+<PARA>
+</PARA>
+</REFSECT1>
+<REFSECT1 ID="R1-1007-UNMANAGECHILDREN-4">
+<TITLE>Structures
+</TITLE>
+<PARA>The <TYPE>WidgetList</TYPE> type is simply an array of widgets:
+</PARA>
+<SCREEN ID="SC-1007-UNMANAGECHILDREN-1">typedef Widget *WidgetList;
+</SCREEN>
+</REFSECT1></REFENTRY> \ No newline at end of file
diff --git a/doc/manpage.man b/doc/manpage.man
new file mode 100644
index 0000000..438bcca
--- /dev/null
+++ b/doc/manpage.man
@@ -0,0 +1,140 @@
+...\" $Header$
+...\"
+...\" transcript compatibility for postscript use.
+...\"
+...\" synopsis: .P! <file.ps>
+...\"
+.de P!
+.fl
+\!!1 setgray
+.fl
+\\&.\"
+.fl
+\!!0 setgray
+.fl \" force out current output buffer
+\!!save /psv exch def currentpoint translate 0 0 moveto
+\!!/showpage{}def
+.fl \" prolog
+.sy sed -e 's/^/!/' \\$1\" bring in postscript file
+\!!psv restore
+.
+.de pF
+.ie \\*(f1 .ds f1 \\n(.f
+.el .ie \\*(f2 .ds f2 \\n(.f
+.el .ie \\*(f3 .ds f3 \\n(.f
+.el .ie \\*(f4 .ds f4 \\n(.f
+.el .tm ? font overflow
+.ft \\$1
+..
+.de fP
+.ie !\\*(f4 \{\
+. ft \\*(f4
+. ds f4\"
+' br \}
+.el .ie !\\*(f3 \{\
+. ft \\*(f3
+. ds f3\"
+' br \}
+.el .ie !\\*(f2 \{\
+. ft \\*(f2
+. ds f2\"
+' br \}
+.el .ie !\\*(f1 \{\
+. ft \\*(f1
+. ds f1\"
+' br \}
+.el .tm ? font underflow
+..
+.ds f1\"
+.ds f2\"
+.ds f3\"
+.ds f4\"
+.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n
+.TH "XtUnmanageChildren" "3
+"
+.SH "NAME"
+XtUnmanageChildren \(em remove a list of children from a parent widget\&'s managed list\&.
+.iX "widgets" "removing"
+.iX "XtUnmanageChildren"
+.SH "SYNOPSIS"
+4 March 1996;
+.PP
+.nf
+void XtUnmanageChildren(\fIchildren\fP, \fInum_children\fP)
+ WidgetList \fIchildren\fP;
+ Cardinal \fInum_children\fP;
+.fi
+.SS "Inputs"
+6 March 1996;
+.IP "\fIchildren\fP" 10
+Specifies an array of child widgets\&. Each child must be of
+class RectObj or any subclass thereof\&.
+.IP "\fInum_children\fP" 10
+Specifies the number of elements in \fIchildren\fP\&.
+.SS "Subsidiary Inputs"
+.PP
+Inputs into unmanageable children may also include
+food, drink, and discipline\&.
+.SH "Description"
+5 March 1996;
+.PP
+\fBXtUnmanageChildren()\fP unmaps the specified widgets
+and removes them from their parent\&'s geometry management\&.
+The widgets will disappear from the screen, and (depending
+on its parent) may no longer have screen space allocated for
+them\&.
+.PP
+Each of the widgets in the \fIchildren\fP array must have
+the same parent\&.
+.PP
+See the Algorithm section below for full details of the
+widget unmanagement procedure\&.
+.SH "Usage"
+.PP
+Unmanaging widgets is the usual method for temporarily
+making them invisible\&. They can be re-managed with
+\fBXtManageChildren()\fP\&.
+.PP
+You can unmap a widget, but leave it under geometry
+management by calling \fBXtUnmapWidget()\fP\&. You can
+destroy a widget\&'s window without destroying the widget by
+calling \fBXtUnrealizeWidget()\fP\&. You can destroy a
+widget completely with \fBXtDestroyWidget()\fP\&.
+.PP
+If you are only going to unmanage a single widget, it is
+more convenient to call \fBXtUnmanageChild()\fP\&. It is
+often more convenient to call \fBXtUnmanageChild()\fP
+several times than it is to declare and initialize an array
+of widgets to pass to \fBXtUnmanageChildren()\fP\&. Calling
+\fBXtUnmanageChildren()\fP is more efficient, however,
+because it only calls the parent\&'s \fBchange_managed()\fP
+method once\&.
+.SH "Algorithm"
+.PP
+\fBXtUnmanageChildren()\fP performs the following:
+.IP "" 10
+Issues an error if the children do not all have the same
+parent or if the parent is not a subclass of
+\fBcompositeWidgetClass\fP\&.
+.IP "" 10
+Returns immediately if the common parent is being destroyed;
+otherwise, for each unique child on the list,
+\fBXtUnmanageChildren()\fP performs the following:
+.IP "-" 10
+Ignores the child if it already is unmanaged or is being
+destroyed\&.
+.IP "-" 10
+Otherwise, if the child is realized, it makes it nonvisible
+by unmapping it\&.
+.IP "" 10
+Calls the \fBchange_managed()\fP method of the widgets\&'
+parent if the parent is realized\&.
+.PP
+.SH "Structures"
+.PP
+The \fBWidgetList\fP type is simply an array of widgets:
+.PP
+.nf
+typedef Widget *WidgetList;
+.fi
+...\" created by instant / docbook-to-man, Mon 31 Aug 1998, 22:15
diff --git a/doc/notes.txt b/doc/notes.txt
new file mode 100644
index 0000000..7fd9041
--- /dev/null
+++ b/doc/notes.txt
@@ -0,0 +1,180 @@
+
+GTK Reference Documentation Notes
+===============================
+
+Things to include:
+ Compiling with GTK - gtk-config, gtk.m4, debugging options.
+ g_warning, g_return_if_fail etc. - though these are in glib.
+ Initialising the GTK library and entering the main loop.
+ Widgets (see below)
+ Object data hash (& GINT_TO_POINTER-type macros)
+ Type functions
+ Ref counting
+ Widget Layout - size_request/size_allocate, coordinate system, X windows.
+ Styles
+ Accelerators - major changes for GTK 1.1
+ Signals - signal emission procedure, connecting to signals, stopping,
+ adding new signals for new widgets, marshaller functions.
+ X Events - signals ending in "_event" have extra param, event masks
+ Keyboard input - focus, CAN_FOCUS, GRAB_FOCUS
+ Default widgets - CAN_DEFAULT, HAS_DEFAULT
+ Args - not complete yet.
+ Drag-and-drop
+ Selections
+ Timers
+ AddInput
+ RC files
+ Factories - major changes for GTK 1.1
+
+ Indices - functions, signals,
+ widget hierarchy/alphabetical list/grouped - annotated
+
+
+For each widget:
+
+ (We include a brief summary of the widget and its functions/signals at the
+ top of the page, since a lot of the time people know how it works but
+ have just forgotten a prototype or variable name.)
+
+ * Name
+ * Ancestors in widget hierarchy, with hyperlinks and set out like Java docs.
+ Short description.
+ ? '#Include <gtk/gtkbutton.h>' line?
+ * Index of functions, with prototypes, hyperlinks to descriptions below.
+ ? Index of useful members of widget struct, hyperlinks to descriptions below.
+ * Index of signals, with prototypes of signal handlers, and hyperlinks to
+ descriptions below.
+ * Standard widget functions and macros, with hyperlinks.
+ Usage - example code covering common use of the widget, which may also use
+ ancestor's properties, e.g. gtk_misc_set_alignment (GTK_MISC (label)...
+ + Full description of functions. Show parameters listed like Java docs?
+ A lot of the time there will just be one param - the widget itself.
+ + Full description of struct members. Show how to access using macro?
+ + Full description of signals.
+ + Full description of standard functions and macros.
+ See Also section showing related widgets, mainly for the man pages.
+
+ Could also be some structs or enums which are used by the widget, e.g.
+ the GtkTableChild/GtkPackerChild structs. Do we keep the enums separate?
+ Or put them with the widget if they are only relevant to that widget?
+
+ Include screenshots?
+
+ + Include Args? - These still aren't fully supported, and they duplicate
+ the functionality already available, but should probably be included.
+
+
+Issues:
+
+ Some things have/will change between different GTK versions so we have to
+ show the changes somehow - a 'deprecated' icon/entity/label or possibly
+ show the version of GTK which each item was added to, e.g. a GTK 1.1 icon.
+ 'Added in GTK 1.1', 'Deprecated in GTK 1.1', 'Not in GTK 1.1' ...
+
+ Cross-references - any time a widget class/type/enum appears there should
+ be a cross-reference (which will turn into a hyperlink for html).
+ But for man pages/printed docs we don't want 'See Also's everywhere.
+ Need to use an easy-to-remember naming scheme for ids - use
+ widget names, function names, enum names as much as possible.
+
+ Glib & GDK documentation - want this to be very similar, and we also need
+ to add cross-references to glib/gdk types and functions. But glib
+ documentation should also be separate?
+
+ For man page output we should include keywords or something to make it
+ easy to find the page with 'man -k' or similar.
+ For printed output we should also index all widgets, functions etc.,
+ so the pages can be found easily.
+ For the HTML version, we should create a database of entry points -
+ widgets, functions, declarations, so that an IDE can easily open up
+ the GTK documentation at a relevant page. e.g. If you move the mouse
+ over a widget in the palette and press F1 it shows the page about
+ the widget.
+
+
+GLib Reference
+==============
+
+Sections:
+ Intro - glib_major_version.
+ Types - gint, gchar, TRUE, FALSE.
+ Type conversion macros - GPOINTER_TO_INT.
+ Limits - G_MINFLOAT etc.
+ Macros - MIN, MAX, ABS, CLAMP, G_ENUM, G_STMT_START, G_GNUC_PRINTF,
+ G_GNUC_FUNCTION, ATEXIT.
+ Memory allocation - g_new, g_new0, g_malloc, g_mem_chunk_create,
+ g_chunk_new.
+ Warnings/assertions - g_assert, g_return_if_fail, g_error, g_warning.
+ Timers.
+ String utility functions.
+ Utility functions - g_get_user_name, g_get_home_dir, g_snprintf.
+ Scanner.
+ Modules.
+ Completion.
+
+ Data structures:
+ Doubly-linked lists.
+ Singly-linked lists.
+ Hash tables & hash functions - beware of adding pointers to
+ dynamically-allocated memory! - it may never be freed.
+ Caches.
+ Trees.
+ Strings.
+ String chunks.
+ Resizable arrays.
+ Resizable pointer arrays.
+ Byte arrays.
+ Quarks ??
+ Datasets.
+ Relation & Tuples.
+
+
+
+Reference Material
+==================
+
+GTK Specific Stuff:
+
+ GTK info pages
+ - a number of widgets & functions are documented, as well as some more
+ general GTK programming topics, e.g. signals, object data.
+
+ GTK tutorial
+ - has descriptions of many widgets.
+
+ Shawn Admundson's example man page
+ - nice structure, includes brief reference material at top and more
+ detailed descriptions below which is good (like Java docs). Also
+ has a 'Usage' section which describes common usage.
+ Doesn't include GTK Args, or useful members of the widget struct.
+
+ gtk+/gtk/testgtk gtk+/examples
+ - lots of example code.
+
+
+Documentation of other languages/toolkits:
+
+ Gnome's DocBook documentation.
+ - gnome-libs/gnome-hello has a basic DocBook document.
+ - perl script in gnome-libs/devel-docs/gdoc - what does it do??
+ - gnome-libs/devel-docs/gnome-dev-info.sgml has lots of stuff:
+ uses '<!entity libgnome SYSTEM ...' to include other docs.
+ pinch the bookinfo & license stuff.
+ has tags: 'screenshot', 'graphic', 'ulink', 'email'
+ '<programlisting role="C">', 'literal', 'prompt', 'userinput'
+ 'function', 'funcsynopsis', 'funcdef' 'paramdef', 'parameter'
+
+ Java documentation
+ - has a very nice structure and nice graphics to make it more
+ attractive, cross-references, describes every function param.
+
+ QT documentation
+ - nice structure, screenshots, cross-references.
+
+ man manual page
+ - we want to output man pages, so we should try to keep close to
+ the standard parts etc. (Use section 3 - library functions)
+ From man man page:
+ 'They may be labelled NAME, SYNOPSIS, DESCRIPTION, OPTIONS,
+ FILES, SEE ALSO, BUGS, and AUTHOR.'
+ see man (7) for the troff macros available (on Linux anyway).
diff --git a/gtk-doc.cat b/gtk-doc.cat
new file mode 100644
index 0000000..5a61f26
--- /dev/null
+++ b/gtk-doc.cat
@@ -0,0 +1,4 @@
+ -- ...................................................................... --
+ -- Modified GTK+ DocBook driver file .................................................. --
+
+PUBLIC "-//Gnome//DTD DocBook V3.0 extension//EN" "gtk-doc.dtd"
diff --git a/gtk-doc.dsl.in b/gtk-doc.dsl.in
new file mode 100644
index 0000000..216c037
--- /dev/null
+++ b/gtk-doc.dsl.in
@@ -0,0 +1,206 @@
+<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" [
+<!ENTITY dbstyle SYSTEM "@DSSSL_DIR@/html/docbook.dsl" CDATA DSSSL>
+]>
+
+<style-sheet>
+<style-specification use="docbook">
+<style-specification-body>
+
+;; These are some customizations to the standard HTML output produced by the
+;; Modular DocBook Stylesheets.
+;; I've copied parts of a few functions from the stylesheets so these should
+;; be checked occasionally to ensure they are up to date.
+
+;;(define %generate-book-toc% #f)
+
+(define %use-id-as-filename% #t)
+
+(define %html-ext% ".html")
+
+(define %shade-verbatim% #t)
+
+
+;; I want to change this so that for programlisting we use a blue background,
+;; but for example or informalexample we use green.
+(define %shade-verbatim-attr-2%
+ ;; Attributes used to create a shaded verbatim environment.
+ (lambda ()
+ (if (or (equal? (gi (parent (current-node)))
+ (normalize "example"))
+ (equal? (gi (parent (current-node)))
+ (normalize "informalexample")))
+ (list
+ (list "BORDER" "0")
+ (list "BGCOLOR" "#E8F8E8")
+ (list "WIDTH" "100%")
+ (list "CELLPADDING" "6"))
+ (list
+ (list "BORDER" "0")
+ (list "BGCOLOR" "#E8E8F8")
+ (list "WIDTH" "100%")
+ (list "CELLPADDING" "6"))
+ )
+ )
+)
+
+;; This overrides $verbatim-display$ (copied from 1.20, dbverb.dsl).
+;; It simply changes %shade-verbatim-attr% to (%shade-verbatim-attr-2%) so we
+;; can use our own function to set the different verbatim colours.
+(define ($verbatim-display$ line-numbers?)
+ (let ((content (make element gi: "PRE"
+ attributes: (list
+ (list "CLASS" (gi)))
+ (if line-numbers?
+ ($verbatim-content-with-linenumbers$)
+ ($verbatim-content$)))))
+ (if %shade-verbatim%
+ (make element gi: "TABLE"
+ attributes: (%shade-verbatim-attr-2%)
+ (make element gi: "TR"
+ (make element gi: "TD"
+ content)))
+ content)))
+
+
+;; This overrides the tgroup definition (copied from 1.20, dbtable.dsl).
+;; It changes the table background color, cell spacing and cell padding.
+(element tgroup
+ (let* ((wrapper (parent (current-node)))
+ (frameattr (attribute-string (normalize "frame") wrapper))
+ (pgwide (attribute-string (normalize "pgwide") wrapper))
+ (footnotes (select-elements (descendants (current-node))
+ (normalize "footnote")))
+ (border (if (equal? frameattr (normalize "none"))
+ '(("BORDER" "0"))
+ '(("BORDER" "1"))))
+ (bgcolor '(("BGCOLOR" "#FFE0E0")))
+ (width (if (equal? pgwide "1")
+ (list (list "WIDTH" ($table-width$)))
+ '()))
+ (head (select-elements (children (current-node)) (normalize "thead")))
+ (body (select-elements (children (current-node)) (normalize "tbody")))
+ (feet (select-elements (children (current-node)) (normalize "tfoot"))))
+ (make element gi: "TABLE"
+ attributes: (append
+ border
+ width
+ bgcolor
+ '(("CELLSPACING" "0"))
+ '(("CELLPADDING" "4"))
+ (if %cals-table-class%
+ (list (list "CLASS" %cals-table-class%))
+ '()))
+ (process-node-list head)
+ (process-node-list body)
+ (process-node-list feet)
+ (make-table-endnotes))))
+
+;; This overrides the refsect2 definition (copied from 1.20, dbrfntry.dsl).
+;; It puts a horizontal rule after each function/struct/... description.
+(element refsect2
+ (make sequence
+ (make empty-element gi: "HR")
+ ($block-container$)))
+
+;; Override the book declaration, so that we generate a crossreference
+;; for the book
+
+(element book
+ (let* ((bookinfo (select-elements (children (current-node)) (normalize "bookinfo")))
+ (ititle (select-elements (children bookinfo) (normalize "title")))
+ (title (if (node-list-empty? ititle)
+ (select-elements (children (current-node)) (normalize "title"))
+ (node-list-first ititle)))
+ (nl (titlepage-info-elements (current-node) bookinfo))
+ (tsosofo (with-mode head-title-mode
+ (process-node-list title)))
+ (dedication (select-elements (children (current-node)) (normalize "dedication"))))
+ (make sequence
+ (html-document
+ tsosofo
+ (make element gi: "DIV"
+ attributes: '(("CLASS" "BOOK"))
+ (if %generate-book-titlepage%
+ (make sequence
+ (book-titlepage nl 'recto)
+ (book-titlepage nl 'verso))
+ (empty-sosofo))
+
+ (if (node-list-empty? dedication)
+ (empty-sosofo)
+ (with-mode dedication-page-mode
+ (process-node-list dedication)))
+
+ (if (not (generate-toc-in-front))
+ (process-children)
+ (empty-sosofo))
+
+ (if %generate-book-toc%
+ (build-toc (current-node) (toc-depth (current-node)))
+ (empty-sosofo))
+
+ ;; (let loop ((gilist %generate-book-lot-list%))
+ ;; (if (null? gilist)
+ ;; (empty-sosofo)
+ ;; (if (not (node-list-empty?
+ ;; (select-elements (descendants (current-node))
+ ;; (car gilist))))
+ ;; (make sequence
+ ;; (build-lot (current-node) (car gilist))
+ ;; (loop (cdr gilist)))
+ ;; (loop (cdr gilist)))))
+
+ (if (generate-toc-in-front)
+ (process-children)
+ (empty-sosofo))))
+ (make entity
+ system-id: "index.sgml"
+ (with-mode generate-index-mode
+ (process-children))))))
+
+;; Honor href="" attributes in anchors
+
+(define (href-to target)
+ ;; Return the HTML HREF for the given node. If nochunks is true, just
+ ;; return the fragment identifier.
+ (let* ((id (element-id target))
+ (href (attribute-string "href" target))
+ (curdepth (directory-depth (html-file (current-node))))
+ (entfile (html-file target))
+ (fragid (if (chunk? target)
+ ""
+ (string-append "#" id))))
+ (if href
+ (string-append (copy-string "../" (+ curdepth 1)) href)
+ (if nochunks
+ fragid
+ (string-append (copy-string "../" curdepth) entfile fragid)))))
+
+;; Mode for generating cross references
+
+(define (process-child-elements)
+ (process-node-list
+ (node-list-map (lambda (snl)
+ (if (equal? (node-property 'class-name snl) 'element)
+ snl
+ (empty-node-list)))
+ (children (current-node)))))
+
+(mode generate-index-mode
+ (element anchor
+ (if (attribute-string "href" (current-node))
+ (empty-sosofo)
+ (make formatting-instruction data:
+ (string-append "\less-than-sign;ANCHOR id =\""
+ (attribute-string "id" (current-node))
+ "\" href=\""
+ (href-to (current-node))
+ "\"\greater-than-sign;
+"))))
+ (default
+ (process-child-elements)))
+
+</style-specification-body>
+</style-specification>
+<external-specification id="docbook" document="dbstyle">
+</style-sheet>
diff --git a/gtk-doc.dtd b/gtk-doc.dtd
new file mode 100644
index 0000000..61d229e
--- /dev/null
+++ b/gtk-doc.dtd
@@ -0,0 +1,10 @@
+<!-- Add an href attribute to the ANCHOR element -->
+
+<!ENTITY % local.anchor.attrib
+"HRef CDATA #IMPLIED">
+
+<!-- ...................................................................... -->
+ <!-- Original DTD ......................................................... -->
+
+<!ENTITY % orig-docbook PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
+%orig-docbook;
diff --git a/gtkdoc-mkdb b/gtkdoc-mkdb
new file mode 100755
index 0000000..71b6ee6
--- /dev/null
+++ b/gtkdoc-mkdb
@@ -0,0 +1,1159 @@
+#!/usr/bin/perl -w
+#
+# Perl script to automatically-generate DocBook documentation for GTK, GDK and
+# GLIB.
+#
+# NOTE: There is a special case when creating the ID for G-CSET-A-2-Z (and
+# also GTK_WIDGET_BASIC).
+# Since IDs are case-insensitive it clashes with G-CSET-a-2-z, so we change it
+# to G-CSET-A-2-Z-CAPS. Maybe we should add a checksum suffix or something so
+# that the case of the ID will never be a problem. But then they become
+# impossible to type in manually.
+
+use Getopt::Long;
+
+# Options
+
+# name of documentation module
+my $PART;
+my $DOCS_DIR;
+my $SGML_OUTPUT_DIR;
+
+%optctl = (module => \$PART,
+ 'output-dir' => \$SGML_OUTPUT_DIR,
+ 'tmpl-dir' => \$DOCS_DIR);
+GetOptions(\%optctl, "module=s", "output-dir:s");
+
+$ROOT_DIR = ".";
+
+# All the files are written in subdirectories beneath here.
+$DOCS_DIR = $DOCS_DIR ? $DOCS_DIR : "$ROOT_DIR/tmpl";
+
+# This is where we put all the DocBook output.
+$SGML_OUTPUT_DIR = $SGML_OUTPUT_DIR ? $SGML_OUTPUT_DIR : "$ROOT_DIR/sgml";
+
+# This file contains the object hierarchy.
+$OBJECT_TREE_FILE = "$ROOT_DIR/$PART.hierarchy";
+
+# This file contains signal arguments and names.
+$SIGNALS_FILE = "$ROOT_DIR/$PART.signals";
+
+# Create the top output directory if it doens't exist.
+if (! -e $SGML_OUTPUT_DIR) {
+ mkdir ("$SGML_OUTPUT_DIR", 0777)
+ || die "Can't create directory: $SGML_OUTPUT_DIR";
+}
+
+# Create the part output directory if it doesn't exist.
+if (! -e "$SGML_OUTPUT_DIR/$PART") {
+ mkdir ("$SGML_OUTPUT_DIR/$PART", 0777)
+ || die "Can't create directory: $SGML_OUTPUT_DIR/$PART";
+}
+
+# Function and other declaration output settings.
+$RETURN_TYPE_FIELD_WIDTH = 12;
+$SYMBOL_FIELD_WIDTH = 32;
+
+$SIGNAL_FIELD_WIDTH = 12;
+
+&ReadSignalsFile;
+&ReadObjectHierarchy;
+
+# XXX this needs to be fixed
+$HEADER_FILE = "gtk/gtk.h";
+&ReadDeclarationsFile ("$ROOT_DIR/$PART-decl.txt", 0);
+if (-f "$ROOT_DIR/$PART-overrides.txt") {
+ &ReadDeclarationsFile ("$ROOT_DIR/$PART-overrides.txt", 1);
+}
+&OutputSGML ("$ROOT_DIR/$PART-sections.txt");
+&CheckAllDeclarationsOutput;
+
+
+# This reads in a file containing the function/macro/enum etc. declarations.
+#
+# Note that in some cases there are several declarations with the same name,
+# e.g. for conditional macros. In this case we set a flag in the
+# %DeclarationConditional hash so the declaration is not shown in the docs.
+#
+# If a macro and a function have the same name, e.g. for gtk_object_ref,
+# the function declaration takes precedence.
+#
+# Some opaque structs are just declared with 'typedef _name name;' in which
+# case the declaration may be empty. The structure may have been
+# found later in the header, so that overrides the empty declaration.
+#
+
+sub ReadDeclarationsFile {
+ local ($file, $override) = @_;
+
+ if ($override == 0) {
+ %Declarations = ();
+ %DeclarationTypes = ();
+ %DeclarationConditional = ();
+ %DeclarationOutput = ();
+ }
+
+ open (INPUT, $file)
+ || die "Can't open $file";
+ $declaration_type = "";
+ while (<INPUT>) {
+ if (!$declaration_type) {
+ if (m/^<([^>]+)>/) {
+ $declaration_type = $1;
+ $declaration_name = "";
+# print "Found declaration: $declaration_type\n";
+ $declaration = "";
+ }
+ } else {
+ if (m%^<NAME>(.*)</NAME>%) {
+ $declaration_name = $1;
+ } elsif (m%^</$declaration_type>%) {
+# print "Found end of declaration: $declaration_name\n";
+ # Check that the declaration has a name
+ if ($declaration_name eq "") {
+ print "ERROR: $declaration_type has no name $file:$.\n";
+ }
+
+ # Check if the symbol is already defined.
+ if (defined ($Declarations{$declaration_name})
+ && $override == 0) {
+ # Function declarations take precedence.
+ if ($DeclarationTypes{$declaration_name} eq 'FUNCTION') {
+ # Ignore it.
+ } elsif ($declaration_type eq 'FUNCTION') {
+ $Declarations{$declaration_name} = $declaration;
+ $DeclarationTypes{$declaration_name} = $declaration_type;
+ } elsif ($DeclarationTypes{$declaration_name}
+ eq $declaration_type) {
+ # If the existing declaration is empty override it.
+ if ($declaration_type eq 'STRUCT') {
+ if ($Declarations{$declaration_name} =~ m/^\s*$/) {
+ $Declarations{$declaration_name} = $declaration;
+ } elsif ($declaration =~ m/^\s*$/) {
+ # Ignore an empty declaration.
+ } else {
+ print "WARNING: Structure has multiple definitions: $declaration_name\n";
+ }
+
+ } else {
+ # set flag in %DeclarationConditional hash for
+ # multiply defined macros/typedefs.
+ $DeclarationConditional{$declaration_name} = 1;
+ }
+ } else {
+ print "ERROR: $declaration_name has multiple definitions\n";
+ }
+ } else {
+ $Declarations{$declaration_name} = $declaration;
+ $DeclarationTypes{$declaration_name} = $declaration_type;
+ }
+ $declaration_type = "";
+ } else {
+ $declaration .= $_;
+ }
+ }
+ }
+ close (INPUT);
+}
+
+
+# This reads all the GTK objects from the output of GLE's gtkquery.
+# It places them in the @objects array, and places their level in the widget
+# hierarchy in the @object_levels array, at the same index.
+# GtkObject, the root object, has a level of 1.
+sub ReadObjectHierarchy {
+ @objects = ();
+ @object_levels = ();
+
+ if (!open (INPUT, $OBJECT_TREE_FILE)) {
+ warn "Can't open $OBJECT_TREE_FILE - skipping object tree\n";
+ return;
+ }
+ open (OUTPUT, ">$SGML_OUTPUT_DIR/tree_index.sgml")
+ || die "Can't create $SGML_OUTPUT_DIR/tree_index.sgml";
+ print (OUTPUT "<literallayout>\n");
+
+ while (<INPUT>) {
+ if (m/Gtk\S+/) {
+ $object = $&;
+ $level = (length($`)) / 2 + 1;
+# print ("Level: $level Object: $object\n");
+
+ $type_link = &GetTypeLink ($object);
+ print (OUTPUT ' ' x ($level * 4), "$type_link\n");
+ push (@objects, $object);
+ push (@object_levels, $level);
+ }
+ }
+ print (OUTPUT "</literallayout>\n");
+
+ close (INPUT);
+ close (OUTPUT);
+
+ &OutputObjectList(@objects);
+}
+
+
+# This outputs the alphabetical list of objects.
+# Note: It also outputs object/data/adjustment etc. - not just widgets.
+sub OutputObjectList {
+ local(@objects) = @_;
+ local($COLS) = 3;
+
+ open (OUTPUT, ">$SGML_OUTPUT_DIR/object_index.sgml")
+ || die "Can't create $SGML_OUTPUT_DIR/object_index.sgml";
+ print (OUTPUT <<EOF);
+<informaltable pgwide=1 frame="none">
+<tgroup cols="$COLS">
+<colspec colwidth="1*">
+<colspec colwidth="1*">
+<colspec colwidth="1*">
+<tbody>
+EOF
+
+ $count = 0;
+ foreach $object (sort(@objects)) {
+ $type_link = &GetTypeLink ($object);
+ if ($count % $COLS == 0) { print (OUTPUT "<row>\n"); }
+ print (OUTPUT "<entry>$type_link</entry>\n");
+ if ($count % $COLS == ($COLS - 1)) { print (OUTPUT "</row>\n"); }
+ $count++;
+ }
+
+ print (OUTPUT <<EOF);
+</tbody></tgroup></informaltable>
+EOF
+ close (OUTPUT);
+}
+
+
+# This reads in an existing file which contains information on all GTK signals.
+# It creates the arrays @SignalNames and @SignalPrototypes containing info on
+# the signals. The first line of the SignalPrototype is the return type of
+# the signal handler. The remaining lines are the parameters passed to it.
+# The last parameter, "gpointer user_data" is always the same so is not
+# included.
+sub ReadSignalsFile {
+ @SignalObjects = ();
+ @SignalNames = ();
+ @SignalReturns = ();
+ @SignalPrototypes = ();
+
+ if (!open (INPUT, $SIGNALS_FILE)) {
+ warn "Can't open $SIGNALS_FILE - skipping signals\n";
+ return;
+ }
+ $in_signal = 0;
+ while (<INPUT>) {
+ if (!$in_signal) {
+ if (m/^<SIGNAL>/) {
+ $in_signal = 1;
+ $signal_object = "";
+ $signal_name = "";
+ $signal_returns = "";
+ $signal_prototype = "";
+ }
+ } else {
+ if (m/^<NAME>(.*)<\/NAME>/) {
+ $signal_name = $1;
+ if ($signal_name =~ m/^(.*)::(.*)$/) {
+ $signal_object = $1;
+ $signal_name = $2;
+# print "Found signal: $signal_name\n";
+ } else {
+ print "Invalid signal name: $signal_name\n";
+ }
+ } elsif (m/^<RETURNS>(.*)<\/RETURNS>/) {
+ $signal_returns = $1;
+ } elsif (m%^</SIGNAL>%) {
+# print "Found end of signal: ${signal_object}::${signal_name}\nReturns: ${signal_returns}\n${signal_prototype}";
+ push (@SignalObjects, $signal_object);
+ push (@SignalNames, $signal_name);
+ push (@SignalReturns, $signal_returns);
+ push (@SignalPrototypes, $signal_prototype);
+ $in_signal = 0;
+ } else {
+ $signal_prototype .= $_;
+ }
+ }
+ }
+ close (INPUT);
+}
+
+
+
+# This collects the output for each section of the docs, and outputs
+# each file when the end of the section is found.
+sub OutputSGML {
+ local ($file) = $_[0];
+ print "Reading: $file\n";
+ open (INPUT, $file)
+ || die "Can't open $file";
+ $book_top = "";
+ $book_bottom = "";
+ $title = "";
+ my ($subsection) = "";
+ while (<INPUT>) {
+ if (m/^#/) {
+ next;
+
+ } elsif (m/^<SECTION>/) {
+ $synop = "";
+ $desc = "";
+ $num_symbols = 0;
+
+ } elsif (m/^<SUBSECTION>/) {
+ $synop .= "\n";
+
+ } elsif (m/^<TITLE>(.*)<\/TITLE>/) {
+ $title = $1;
+# print "Section: $title\n";
+
+ # We don't want warnings if object & class structs aren't used.
+ $DeclarationOutput{$title} = 1;
+ $DeclarationOutput{"${title}Class"} = 1;
+
+ } elsif (m/^<FILE>(.*)<\/FILE>/) {
+ $file = $1;
+ &ReadDoc ($file);
+
+ } elsif (m/^<NAME>(.*)<\/NAME>/) {
+ $subsection = $1;
+
+ } elsif (m/^<\/SECTION>/) {
+ if ($title eq "") {
+ $title = $file;
+ }
+# print "End of section: $title\n";
+
+ $file =~ s/\s/_/g;
+ $file .= ".sgml";
+
+ # GtkObjects use their class name as the ID.
+ if (&CheckIsObject ($title)) {
+ $section_id = &CreateValidSGMLID ($title);
+ } else {
+ $section_id = &CreateValidSGMLID ("$PART-$title");
+ }
+
+ if ($num_symbols > 0) {
+ $book_top .= "<!entity $section_id SYSTEM \"sgml/$file\">\n";
+ $book_bottom .= " &$section_id;\n";
+
+ &OutputSGMLFile ($file, $title, $section_id);
+ }
+ $title = "";
+ $subsection = "";
+
+ } elsif (m/^(\S+)/) {
+ $symbol = $1;
+# print " Symbol: $symbol\n";
+
+ $declaration = $Declarations{$1};
+ if (defined ($declaration)) {
+ # We don't want standard macros/functions of GtkObjects.
+ if ($subsection ne "Standard") {
+ &OutputDeclaration ($symbol, $declaration);
+ }
+
+ # Note that the declaration has been output.
+ $DeclarationOutput{$symbol} = 1;
+ } else {
+ print "WARNING: No declaration for: $1\n";
+ }
+ $num_symbols++;
+ }
+ }
+ close (INPUT);
+
+ &OutputBook ($book_top, $book_bottom);
+}
+
+
+# This steps through all the declarations that were loaded, and makes sure
+# that each one has been output, by checking the corresponding flag in the
+# %DeclarationOutput hash. It is intended to check that any new declarations
+# in new version of GTK get added to the gXXX-sections.txt file.
+sub CheckAllDeclarationsOutput {
+ $NumUnused = 0;
+ open (UNUSED, ">$ROOT_DIR/$PART-unused.txt")
+ || die "Can't open $ROOT_DIR/$PART-unused.txt";
+ foreach $symbol (keys (%Declarations)) {
+ if (!defined ($DeclarationOutput{$symbol})) {
+ print (UNUSED "$symbol\n");
+ $NumUnused++;
+ }
+ }
+ close (UNUSED);
+ if ($NumUnused != 0) {
+ print <<EOF;
+=============================================================================
+WARNING: $NumUnused unused declarations.
+ These can be found in $PART-unused.txt.
+ They should be added to $PART-sections.txt in the appropriate place.
+=============================================================================
+EOF
+ }
+}
+
+sub OutputDeclaration {
+ local ($symbol, $declaration) = @_;
+
+ $type = $DeclarationTypes {$symbol};
+ if ($type eq 'MACRO') {
+ &OutputMacro ($symbol, $declaration);
+ } elsif ($type eq 'TYPEDEF') {
+ &OutputTypedef ($symbol, $declaration);
+ } elsif ($type eq 'STRUCT') {
+ &OutputStruct ($symbol, $declaration);
+ } elsif ($type eq 'ENUM') {
+ &OutputEnum ($symbol, $declaration);
+ } elsif ($type eq 'UNION') {
+ &OutputUnion ($symbol, $declaration);
+ } elsif ($type eq 'FUNCTION') {
+ &OutputFunction ($symbol, $declaration, $type);
+ } elsif ($type eq 'USER_FUNCTION') {
+ &OutputFunction ($symbol, $declaration, $type);
+ } else {
+ die "Unknown symbol type";
+ }
+}
+
+sub OutputMacro {
+ local ($symbol, $declaration) = @_;
+ $id = &CreateValidSGMLID ($symbol);
+ $synop .= "#define <link linkend=\"$id\">$symbol</link>";
+ $args = "";
+ if ($declaration =~ m/^\s*#\s*define\s+\w+(\([^\)]*\))/) {
+ $args = $1;
+
+ if (length ($symbol) < $SYMBOL_FIELD_WIDTH) {
+ $synop .= (' ' x ($SYMBOL_FIELD_WIDTH - length ($symbol)));
+ }
+
+ $synop .= &CreateValidSGML ($args);
+ }
+ $synop .= "\n";
+
+ if ($args ne "") {
+ $desc .= "<refsect2>\n<title><anchor id=\"$id\">${symbol}()</title>\n";
+ } else {
+ $desc .= "<refsect2>\n<title><anchor id=\"$id\">$symbol</title>\n";
+ }
+ # Don't output the macro definition if is is a conditional macro or it
+ # looks like a function, i.e. starts with "g_" or "_?gnome_", otherwise we
+ # get lots of complicated macros like g_assert.
+ if (!defined ($DeclarationConditional{$symbol}) && ($symbol !~ m/^g_/)
+ && ($symbol !~ m/^_?gnome_/)) {
+ $declaration = &CreateValidSGML ($declaration);
+ $desc .= "<programlisting>$declaration</programlisting>\n";
+ } else {
+ $desc .= "<programlisting>#define $symbol";
+ $desc .= &CreateValidSGML ($args);
+ $desc .= "</programlisting>\n";
+ }
+ if (defined ($SymbolDocs{$symbol})) {
+ $desc .= &ExpandAbbreviations($SymbolDocs{$symbol});
+ }
+ &OutputParamDescriptions ("macro");
+ $desc .= "</refsect2>\n";
+}
+
+
+sub OutputTypedef {
+ local ($symbol, $declaration) = @_;
+ $id = &CreateValidSGMLID ($symbol);
+ $synop .= "typedef <link linkend=\"$id\">$symbol</link>\n";
+ $desc .= "<refsect2>\n<title><anchor id=\"$id\">$symbol</title>\n";
+ # Don't output the macro definition if is is a conditional macro or it
+ # looks like a function, i.e. starts with "g_"
+ if (!defined ($DeclarationConditional{$symbol})) {
+ $declaration = &CreateValidSGML ($declaration);
+ $desc .= "<programlisting>$declaration</programlisting>\n";
+ }
+ if (defined ($SymbolDocs{$symbol})) {
+ $desc .= &ExpandAbbreviations($SymbolDocs{$symbol});
+ }
+ $desc .= "</refsect2>\n";
+}
+
+
+sub OutputStruct {
+ local ($symbol, $declaration) = @_;
+ $id = &CreateValidSGMLID ($symbol);
+ $synop .= "struct <link linkend=\"$id\">$symbol</link>\n";
+ $desc .= "<refsect2>\n<title><anchor id=\"$id\">$symbol</title>\n";
+ if ($declaration =~ m/^\s*$/) {
+# print "Found opaque struct\n";
+ $declaration = "struct $symbol;";
+ }
+ $declaration = &CreateValidSGML ($declaration);
+ $desc .= "<programlisting>$declaration</programlisting>\n";
+ if (defined ($SymbolDocs{$symbol})) {
+ $desc .= &ExpandAbbreviations($SymbolDocs{$symbol});
+ }
+ $desc .= "</refsect2>\n";
+}
+
+
+sub OutputEnum {
+ local ($symbol, $declaration) = @_;
+ $id = &CreateValidSGMLID ($symbol);
+ $synop .= "enum <link linkend=\"$id\">$symbol</link>\n";
+ $desc .= "<refsect2>\n<title><anchor id=\"$id\">$symbol</title>\n";
+ $declaration = &CreateValidSGML ($declaration);
+ $desc .= "<programlisting>$declaration</programlisting>\n";
+ if (defined ($SymbolDocs{$symbol})) {
+ $desc .= &ExpandAbbreviations($SymbolDocs{$symbol});
+ }
+ $desc .= "</refsect2>\n";
+}
+
+
+sub OutputUnion {
+ local ($symbol, $declaration) = @_;
+ $id = &CreateValidSGMLID ($symbol);
+ $synop .= "union <link linkend=\"$id\">$symbol</link>\n";
+ $desc .= "<refsect2>\n<title><anchor id=\"$id\">$symbol</title>\n";
+ $declaration = &CreateValidSGML ($declaration);
+ $desc .= "<programlisting>$declaration</programlisting>\n";
+ if (defined ($SymbolDocs{$symbol})) {
+ $desc .= &ExpandAbbreviations($SymbolDocs{$symbol});
+ }
+ $desc .= "</refsect2>\n";
+}
+
+
+sub OutputFunction {
+ local ($symbol, $declaration, $symbol_type) = @_;
+ $id = &CreateValidSGMLID ($symbol);
+
+ # Take out the return type
+ $declaration =~ s/<RETURNS>\s*(const\s+|unsigned\s+)*(\w+)\s*(\**)\s*<\/RETURNS>\n//;
+ if (defined($1)) { $type_modifier = $1; }
+ else { $type_modifier = ""; }
+ $type = $2;
+ $pointer = $3;
+ $type_link = &GetTypeLink ($type);
+ $start = "";
+ if ($symbol_type eq 'USER_FUNCTION') {
+# $start = "typedef ";
+ }
+
+ $ret_type_len = length ($start) + length ($type_modifier)
+ + length ($pointer) + length ($type);
+ if ($ret_type_len < $RETURN_TYPE_FIELD_WIDTH) {
+ $ret_type_output = "$start$type_modifier$type_link$pointer"
+ . (' ' x ($RETURN_TYPE_FIELD_WIDTH - $ret_type_len));
+ $symbol_len = 0;
+ } else {
+# $ret_type_output = "$start$type_modifier$type_link$pointer\n"
+# . (' ' x $RETURN_TYPE_FIELD_WIDTH);
+
+ $ret_type_output = "$start$type_modifier$type_link$pointer ";
+ $symbol_len = $ret_type_len + 1 - $RETURN_TYPE_FIELD_WIDTH;
+ }
+
+ $symbol_len += length ($symbol);
+ $char1 = $char2 = $char3 = "";
+ if ($symbol_type eq 'USER_FUNCTION') {
+ $symbol_len += 3;
+ $char1 = "(";
+ $char2 = "*";
+ $char3 = ")";
+ }
+
+ if ($symbol_len < $SYMBOL_FIELD_WIDTH) {
+ $symbol_output = "$char1<link linkend=\"$id\">$char2$symbol</link>$char3"
+ . (' ' x ($SYMBOL_FIELD_WIDTH - $symbol_len));
+ $symbol_desc_output = "$char1$char2$symbol$char3"
+ . (' ' x ($SYMBOL_FIELD_WIDTH - $symbol_len));
+ } else {
+ $symbol_output = "$char1<link linkend=\"$id\">$char2$symbol</link>$char3\n"
+ . (' ' x ($SYMBOL_FIELD_WIDTH + $RETURN_TYPE_FIELD_WIDTH));
+ $symbol_desc_output = "$char1$char2$symbol$char3\n"
+ . (' ' x ($SYMBOL_FIELD_WIDTH + $RETURN_TYPE_FIELD_WIDTH));
+ }
+
+ $synop .= $ret_type_output . $symbol_output . '(';
+ $desc .= "<refsect2>\n<title><anchor id=\"$id\">${symbol}()</title>\n";
+ $desc .= "<programlisting>${ret_type_output}$symbol_desc_output(";
+
+ $param_num = 0;
+ while ($declaration ne "") {
+ if ($declaration =~ s/^[\s,]+//) {
+ # skip whitespace and commas
+ next;
+
+ } elsif ($declaration =~ s/^void\s*[,\n]//) {
+ $synop .= "void";
+ $desc .= "void";
+
+ } elsif ($declaration =~ s/^...\s*[,\n]//) {
+ if ($param_num == 0) {
+ $synop .= "...";
+ $desc .= "...";
+ } else {
+ $synop .= ",\n"
+ . (' ' x ($SYMBOL_FIELD_WIDTH + $RETURN_TYPE_FIELD_WIDTH))
+ . " ...";
+ $desc .= ",\n"
+ . (' ' x ($SYMBOL_FIELD_WIDTH + $RETURN_TYPE_FIELD_WIDTH))
+ . " ...";
+ }
+
+ # allow alphanumerics, '_', '[' & ']' in param names
+ } elsif ($declaration =~ s/^(const\s+|unsigned\s+)*(struct\s+)?(\w+)\s*(\**)\s*(const\s+)?(\**)?\s*(\w+)?\s*(\[\])?\s*[,\n]//) {
+ if (defined($1)) { $mod1 = $1; }
+ else { $mod1 = ""; }
+ if (defined($2)) { $mod1 .= $2; }
+ $type = $3;
+ $ptr1 = $4;
+ if (defined($5)) { $mod2 = $5; }
+ else { $mod2 = ""; }
+ $ptr2 = $6;
+ if (defined($7)) {
+ $ptr1 = " " . $ptr1;
+ $name = $7;
+ } else {
+ $name = "";
+ }
+ if (defined($8)) { $array = $8; }
+ else { $array = ""; }
+ $type_link = &GetTypeLink ($type);
+
+# print "Type: $mod1$type $ptr1 $mod2 $name $array\n";
+ if ($param_num == 0) {
+ $synop .= "$mod1$type_link$ptr1$mod2$ptr2$name$array";
+ $desc .= "$mod1$type_link$ptr1$mod2$ptr2$name$array";
+ } else {
+ $synop .= ",\n"
+ . (' ' x ($SYMBOL_FIELD_WIDTH + $RETURN_TYPE_FIELD_WIDTH))
+ . " $mod1$type_link$ptr1$mod2$ptr2$name$array";
+ $desc .= ",\n"
+ . (' ' x ($SYMBOL_FIELD_WIDTH + $RETURN_TYPE_FIELD_WIDTH))
+ . " $mod1$type_link$ptr1$mod2$ptr2$name$array";
+ }
+
+ # Try to match parameters which are functions.
+ } elsif ($declaration =~ s/^(const\s+|unsigned\s+)*(struct\s+)?(\w+)\s*(\**)\s*(const\s+)?\(\s*\*\s*(\w+)\s*\)\s*\(([^)]*)\)\s*[,\n]//) {
+ if (defined($1)) { $mod1 = $1; }
+ else { $mod1 = ""; }
+ if (defined($2)) { $mod1 .= $2; }
+ $type = $3;
+ $ptr1 = $4;
+ if (defined($5)) { $mod2 = $5; }
+ else { $mod2 = ""; }
+ $name = $6;
+ $func_params = $7;
+ $type_link = &GetTypeLink ($type);
+
+# print "Type: $mod1$type$ptr1$mod2(*$name)($func_params)\n";
+ if ($param_num == 0) {
+ $synop .= "$mod1$type_link$ptr1$mod2 (*$name) ($func_params)";
+ $desc .= "$mod1$type_link$ptr1$mod2 (*$name) ($func_params)";
+ } else {
+ $synop .= ",\n"
+ . (' ' x ($SYMBOL_FIELD_WIDTH + $RETURN_TYPE_FIELD_WIDTH))
+ . " $mod1$type_link$ptr1$mod2 (*$name) ($func_params)";
+ $desc .= ",\n"
+ . (' ' x ($SYMBOL_FIELD_WIDTH + $RETURN_TYPE_FIELD_WIDTH))
+ . " $mod1$type_link$ptr1$mod2 (*$name) ($func_params)";
+ }
+
+ } else {
+ print "###Can't parse args for function $symbol: $declaration\n";
+ last;
+ }
+ $param_num++;
+ }
+ $synop .= ");\n";
+ $desc .= ");</programlisting>\n";
+ if (defined ($SymbolDocs{$symbol})) {
+ $desc .= &ExpandAbbreviations($SymbolDocs{$symbol});
+ }
+
+ &OutputParamDescriptions ("function");
+ $desc .= "</refsect2>\n";
+}
+
+sub OutputParamDescriptions {
+ local ($params_type) = $_[0];
+
+ if (defined ($SymbolParams{$symbol})) {
+ undef $returns;
+ $params = $SymbolParams{$symbol};
+ $params_desc = "";
+ if ($#$params < 0) {
+ print "WARNING: 0 parameters\n";
+ }
+ for ($j = 0; $j <= $#$params; $j++) {
+ $param = $$params[$j];
+ if ($param =~ s/^\@(\S+):\s*//) {
+ $param_name = $1;
+ if ($param_name eq "Returns") {
+ $returns = &ExpandAbbreviations($param);
+ } else {
+ if ($param_name eq "Varargs") {
+ $param_name = "...";
+ }
+ $param = &ExpandAbbreviations($param);
+ $params_desc .= "<row><entry align=\"right\"><parameter>$param_name</parameter>&nbsp;:</entry>\n<entry>$param</entry></row>\n";
+ }
+ } else {
+ print "ERROR: Can't parse parameter name\n";
+ }
+ }
+
+ # Signals have an implicit user_data parameter which we describe.
+ if ($params_type eq "signal") {
+ $params_desc .= "<row><entry align=\"right\"><parameter>user_data</parameter>&nbsp;:</entry>\n<entry>user data set when the signal handler was connected.</entry></row>\n";
+ }
+
+ # Start a table if we need one.
+ if ($params_desc ne "" || defined ($returns)) {
+ $desc .= <<EOF;
+<informaltable pgwide=1 frame="none">
+<tgroup cols="2">
+<colspec colwidth="2*">
+<colspec colwidth="8*">
+<tbody>
+EOF
+
+ if ($params_desc ne "") {
+# $desc .= "<row><entry>Parameters:</entry></row>\n";
+ $desc .= $params_desc;
+ }
+
+ # Output the returns info last.
+ if (defined ($returns)) {
+ $desc .= "<row><entry align=\"right\"><emphasis>Returns</emphasis> :</entry><entry>$returns</entry></row>\n";
+ }
+
+ # Finish the table.
+ $desc .= "</tbody></tgroup></informaltable>";
+ }
+ }
+}
+
+
+sub OutputSGMLFile {
+ local ($file, $title, $section_id) = @_;
+
+ # Find out if this is a GtkObject or descendant.
+ $signals_synop = $signals_desc = $hierarchy = "";
+ if (&CheckIsObject ($title)) {
+ ($signals_synop, $signals_desc) = &GetSignals ($title);
+ $hierarchy = &GetHierarchy ($title);
+ }
+
+ # The edited title overrides the one from the sections file.
+ $new_title = $SymbolDocs{"Title"};
+ if (defined ($new_title) && $new_title !~ m/^\s*$/) {
+ $title = $new_title;
+# print "Found title: $title\n";
+ }
+ $short_desc = $SymbolDocs{"Short_Description"};
+ if (!defined ($short_desc) || $short_desc =~ m/^\s*$/) {
+ $short_desc = "one line description goes here.";
+ } else {
+ $short_desc = &ExpandAbbreviations($short_desc);
+# print "Found short_desc: $short_desc";
+ }
+ $long_desc = $SymbolDocs{"Long_Description"};
+ if (!defined ($long_desc) || $long_desc =~ m/^\s*$/) {
+ $long_desc = "<para>\nA longer description goes here.\n</para>\n";
+ } else {
+ $long_desc = &ExpandAbbreviations($long_desc);
+# print "Found long_desc: $long_desc";
+ }
+
+ if ($PART eq 'glib') {
+ $distribution_name = "GLib";
+ } else {
+ $distribution_name = "GTK+";
+ }
+
+ open (OUTPUT, ">$SGML_OUTPUT_DIR/$file")
+ || die "Can't create $SGML_OUTPUT_DIR/$file";
+
+ # Note: The refname and refpurpose are on the same line to stop
+ # docbook-to-man 1.08 putting them on separate lines.
+ print OUTPUT <<EOF;
+<refentry id="$section_id" revision="14 Sep 1998">
+<refmeta>
+<refentrytitle>$title</refentrytitle>
+<manvolnum>3</manvolnum>
+<refmiscinfo>\U$PART\E Library</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>$title</refname><refpurpose>$short_desc</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv><title>Synopsis</title>
+<synopsis>
+
+#include &lt;$HEADER_FILE&gt;
+
+${synop}</synopsis>
+</refsynopsisdiv>
+
+$hierarchy
+$signals_synop
+
+<refsect1>
+<title>Description</title>
+$long_desc
+</refsect1>
+
+<refsect1>
+<title>Details</title>
+$desc
+</refsect1>
+$signals_desc
+
+</refentry>
+EOF
+ close (OUTPUT);
+}
+
+# I'm not sure there's much point in putting this on every page.
+#<refsect1>
+#<title>Authors</title>
+#<para>
+#This manual page was written by XXX
+#<email>anon@nowhere.com</email>.
+#For the authors of $distribution_name, see the <filename>AUTHORS</filename>
+#file in the $distribution_name distribution.
+#</para>
+#</refsect1>
+
+
+sub OutputBook {
+ local ($book_top, $book_bottom) = @_;
+
+ open (OUTPUT, ">$SGML_OUTPUT_DIR/$PART-doc.top")
+ || die "Can't create $SGML_OUTPUT_DIR/$PART-doc.top";
+ print OUTPUT $book_top;
+ close (OUTPUT);
+
+ open (OUTPUT, ">$SGML_OUTPUT_DIR/$PART-doc.bottom")
+ || die "Can't create $SGML_OUTPUT_DIR/$PART-doc.bottom";
+ print OUTPUT $book_bottom;
+ close (OUTPUT);
+}
+
+
+# This creates a valid SGML 'id' from the given string.
+sub CreateValidSGMLID {
+ my ($id) = $_[0];
+
+ # Special case, '_' would end up as '' so we use 'gettext-macro' instead.
+ if ($id eq "_") { return "gettext-macro"; }
+
+ # Special case, differentiate AND, OR and NOT from and, or and not.
+ if ($id eq 'AND') { return "AND-CAPS"; }
+ if ($id eq 'OR') { return "OR-CAPS"; }
+ if ($id eq 'NOT') { return "NOT-CAPS"; }
+
+ # Special case, differentiate Unit from unit.
+ if ($id eq 'Unit') { return "UNIT-CAP"; }
+
+ $id =~ s/[_ ]/-/g;
+ $id =~ s/[,\.]//g;
+ $id =~ s/^-*//;
+
+ # Special case, since ids are case-insensitive G-CSET-A-2-Z clashes with
+ # G-CSET-a-2-z, so we change it to G-CSET-A-2-Z-CAPS
+ if ($id eq 'G-CSET-A-2-Z') { $id = 'G-CSET-A-2-Z-CAPS' };
+
+ # Special case, change GTK-WIDGET-BASIC to GTK-WIDGET-BASIC-CAPS
+ if ($id eq 'GTK-WIDGET-BASIC') { $id = 'GTK-WIDGET-BASIC-CAPS' };
+
+ return $id;
+}
+
+
+# This turns any chars which are used in SGML into entities, e.g. '<' -> '&lt;'
+sub CreateValidSGML {
+ local ($text) = $_[0];
+ $text =~ s/&/&amp;/g; # Do this first, or the others get messed up.
+ $text =~ s/</&lt;/g;
+ $text =~ s/>/&gt;/g;
+ return $text;
+}
+
+
+# This turns the abbreviations function(), macro(), @param, %constant, and
+# #symbol into appropriate DocBook markup.
+sub ExpandAbbreviations {
+ local ($text) = $_[0];
+
+ # Convert 'function()' or 'macro()'
+ $text =~ s/(\w+)\s*\(\)/&GetTypeLink($1) . "()";/eg;
+
+ # Convert '@param'
+ $text =~ s/\@(\w+)/<parameter>$1<\/parameter>/g;
+
+ # Convert '%constant'
+ $text =~ s/\%(\w+)/<literal>$1<\/literal>/g;
+
+ # Convert '#symbol'
+ $text =~ s/#(\w+)/&GetTypeLink($1);/eg;
+
+ return $text;
+}
+
+
+# This returns a cross-reference link to the given type.
+sub GetTypeLink {
+ local ($type) = $_[0];
+# print "Getting type link for $type\n";
+ # Don't create a link for some standard C types and functions.
+ if ($type eq "void" || $type eq "va_list" || $type eq "int"
+ || $type eq "char" || $type eq "printf" || $type eq "sprintf") {
+ return $type;
+ }
+
+ $type_id = &CreateValidSGMLID ($type);
+ return "<link linkend=\"$type_id\">$type</link>";
+}
+
+
+# Returns 1 if the given name is a GtkObject or a descendant.
+sub CheckIsObject {
+ local ($name) = $_[0];
+
+ for ($i = 0; $i <= $#objects; $i++) {
+ if ($objects[$i] eq $name) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+
+# This returns the list of ancestors of a widget.
+# It uses the global @objects and @object_levels arrays to walk up the tree.
+sub GetHierarchy {
+ local ($object) = $_[0];
+
+ # Find object in the objects array.
+ $found = 0;
+# print "looking for: $object\n";
+ for ($i = 0; $i <= $#objects; $i++) {
+# print "$i comparing with: $objects[$i]\n";
+ if ($objects[$i] eq $object) { $found = 1; last; }
+ }
+ if (!$found) {
+# print "not found\n";
+ return "";
+ }
+
+ # Walk up the hierarchy, pushing ancestors onto the ancestors array.
+ local (@ancestors) = ();
+ push (@ancestors, $object);
+ $level = $object_levels[$i];
+# print "Level: $level\n";
+ while ($level > 1) {
+ $i--;
+ if ($object_levels[$i] < $level) {
+ push (@ancestors, $objects[$i]);
+ $level = $object_levels[$i];
+# print "Level: $level\n";
+ }
+ }
+
+ # Output the ancestors list, indented and with links.
+ local ($hierarchy) = "<synopsis>\n\n";
+ $level = 0;
+ for ($i = $#ancestors; $i >= 0; $i--) {
+ # Don't add a link to the current widget, i.e. when i == 0.
+ if ($i > 0) {
+ local ($ancestor_id) = &CreateValidSGMLID ($ancestors[$i]);
+ $link_text = "<link linkend=\"$ancestor_id\">$ancestors[$i]</link>";
+ } else {
+ $link_text = "$ancestors[$i]";
+ }
+ if ($level == 0) {
+ $hierarchy .= " $link_text\n";
+ } else {
+ $hierarchy .= ' ' x ($level * 6 - 3) . "|\n";
+ $hierarchy .= ' ' x ($level * 6 - 3) . "+----$link_text\n";
+ }
+ $level++;
+ }
+ $hierarchy .= "</synopsis>\n";
+
+ return <<EOF;
+<refsect1>
+<title>Object Hierarchy</title>
+$hierarchy
+</refsect1>
+EOF
+}
+
+
+# This returns the signal prototypes for the synopsis and similar for the
+# signal descriptions.
+sub GetSignals {
+ local ($object) = $_[0];
+ local ($proto) = "";
+ local ($desc) = "";
+
+# print "Getting signals for object: $object\n";
+
+ for ($i = 0; $i <= $#SignalObjects; $i++) {
+ if ($SignalObjects[$i] eq $object) {
+# print "Found signal: $SignalNames[$i]\n";
+ $name = $SignalNames[$i];
+ $symbol = "${object}::${name}";
+ $id = &CreateValidSGMLID ("$object-$name");
+
+ $name_len = length ($name) + 2;
+ if ($name_len < $SIGNAL_FIELD_WIDTH) {
+ $proto .= "'<link linkend=\"$id\">$name</link>'"
+ . (' ' x ($SIGNAL_FIELD_WIDTH - $name_len));
+ } else {
+ $proto .= "'<link linkend=\"$id\">$name</link>'\n"
+ . (' ' x $SIGNAL_FIELD_WIDTH);
+ }
+
+ $desc .= "<refsect2><title><anchor id=\"$id\">The '$name' signal</title>\n";
+ $desc .= "<programlisting>";
+
+ $SignalReturns[$i] =~ m/\s*(const\s*)?(\w+)\s*(\**)/;
+ if (defined($1)) { $type_modifier = $1; }
+ else { $type_modifier = ""; }
+ $type = $2;
+ $pointer = $3;
+ $type_link = &GetTypeLink ($type);
+
+ $ret_type_len = length ($type_modifier) + length ($pointer)
+ + length ($type);
+ $ret_type_output = "$type_modifier$type_link$pointer"
+ . (' ' x ($RETURN_TYPE_FIELD_WIDTH - $ret_type_len));
+
+ $proto .= "${ret_type_output}user_function (";
+ $desc .= "${ret_type_output}user_function (";
+
+ @params = split ("\n", $SignalPrototypes[$i]);
+ for ($j = 0; $j <= $#params; $j++) {
+ # allow alphanumerics, '_', '[' & ']' in param names
+ if ($params[$j] =~ m/^\s*(\w+)\s*(\**)\s*([\w\[\]]+)\s*$/) {
+ $type = $1;
+ $pointer = $2;
+ $name = $3;
+ $type_link = &GetTypeLink ($type);
+ $proto .= "$type_link $pointer$name,\n";
+ $proto .= (' ' x ($SYMBOL_FIELD_WIDTH + $RETURN_TYPE_FIELD_WIDTH));
+ $desc .= "$type_link $pointer$name,\n";
+ $desc .= (' ' x ($SYMBOL_FIELD_WIDTH + $RETURN_TYPE_FIELD_WIDTH));
+ } else {
+ print "###Can't parse arg: $params[$j]\nArgs:$SignalPrototypes[$i]\n";
+ }
+ }
+ $type_link = &GetTypeLink ("gpointer");
+ $proto .= "$type_link user_data);\n";
+ $desc .= "$type_link user_data);</programlisting>\n";
+
+ if (defined ($SymbolDocs{$symbol})) {
+ $desc .= &ExpandAbbreviations($SymbolDocs{$symbol});
+ }
+
+ &OutputParamDescriptions ("signal");
+ $desc .= "</refsect2>";
+ }
+ }
+ if ($proto ne '') {
+ $proto = <<EOF;
+<refsect1>
+<title>Signal Prototypes</title>
+<synopsis>
+
+${proto}</synopsis>
+</refsect1>
+EOF
+ $desc = <<EOF;
+<refsect1>
+<title>Signals</title>
+$desc
+</refsect1>
+EOF
+ }
+ return ($proto, $desc);
+}
+
+
+# This reads in the manually-edited documentation file corresponding to the
+# file currently being created, so we can insert the documentation at the
+# appropriate places. It outputs %SymbolDocs and %SymbolParams, which is
+# a hash of hashes.
+sub ReadDoc {
+ local ($file) = $_[0];
+ $docsfile = "$DOCS_DIR/$file.sgml";
+
+ if (! -f $docsfile) {
+ print "File doesn't exist: $docsfile\n";
+ return;
+ }
+
+ open (DOCS, $docsfile)
+ || die "Can't open file: $docsfile";
+
+ %SymbolDocs = ();
+ %SymbolParams = ();
+ $CurrentSymbol = "";
+ $CurrentParam = -1;
+ $SymbolDoc = "";
+ while (<DOCS>) {
+ if (m/^<!-- ##### [A-Z_]+ (\S+) ##### -->/) {
+ $symbol = $1;
+# print "Found symbol: $symbol\n";
+
+ # Store previous symbol, but remove any trailing blank lines.
+ if ($CurrentSymbol ne "") {
+ $SymbolDoc =~ s/\s+$//;
+ $SymbolDocs{$CurrentSymbol} = $SymbolDoc;
+ if ($CurrentParam >= 0) {
+ $SymbolParams{$CurrentSymbol} = [ @Params ];
+ }
+ }
+ $CurrentSymbol = $symbol;
+ $CurrentParam = -1;
+ $SymbolDoc = "";
+ @Params = ();
+ } else {
+ # Check if param found
+ if (m/^\@(\S+):/) {
+ $param_name = $1;
+ # Allow variations of 'Returns'
+ if ($param_name =~ m/^[Rr]eturn/) {
+ $param_name = "Returns";
+ }
+ push (@Params, $_);
+ $CurrentParam++;
+ next;
+ }
+
+ if ($CurrentParam >= 0) {
+ $Params[$CurrentParam] .= $_;
+ } else {
+ $SymbolDoc .= $_;
+ }
+ }
+ }
+
+ # Remember to finish the current symbol doccs.
+ if ($CurrentSymbol ne "") {
+ $SymbolDoc =~ s/\s+$//;
+ $SymbolDocs{$CurrentSymbol} = $SymbolDoc;
+ if ($CurrentParam >= 0) {
+ $SymbolParams{$CurrentSymbol} = [ @Params ];
+ }
+ }
+
+ close (DOCS);
+}
diff --git a/gtkdoc-mkhtml.in b/gtkdoc-mkhtml.in
new file mode 100644
index 0000000..de3ec97
--- /dev/null
+++ b/gtkdoc-mkhtml.in
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+
+usage="\
+Usage: gtkdoc-mkhtml MODULE DRIVER_FILE"
+
+
+if test $# -ne 2; then
+ echo "${usage}" 1>&2
+ exit 1
+fi
+
+module=$1
+
+prefix=@prefix@
+gtkdocdir=@datadir@/gtk-doc/
+
+jade -t sgml -d $gtkdocdir/gtk-doc.dsl -c $gtkdocdir/gtk-doc.cat $2
+sed s%href=\"%href=\"$module/% < index.sgml > index.sgml.tmp && mv index.sgml.tmp index.sgml
diff --git a/gtkdoc-mkman.in b/gtkdoc-mkman.in
new file mode 100644
index 0000000..d557f3b
--- /dev/null
+++ b/gtkdoc-mkman.in
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+
+for i in `cd sgml/gtk;ls *.sgml`
+do j=`echo $i | sed 's/.sgml/.man/'`
+echo ": converting " $i $j
+docbook-to-man sgml/gtk/$i > man/gtk/$j 2> man/gtk-logs/$i.log
+done
+
+for i in `cd sgml/gdk;ls *.sgml`
+do j=`echo $i | sed 's/.sgml/.man/'`
+echo ": converting " $i $j
+docbook-to-man sgml/gdk/$i > man/gdk/$j 2> man/gdk-logs/$i.log
+done
+
+for i in `cd sgml/glib;ls *.sgml`
+do j=`echo $i | sed 's/.sgml/.man/'`
+echo ": converting " $i $j
+docbook-to-man sgml/glib/$i > man/glib/$j 2> man/glib-logs/$i.log
+done
+
+#for i in Man/*
+#do j=`echo $i | sed "s/Man.//"`
+#echo ": formatting " $i $j
+#tbl $i | nroff -man > Out/$j
+#done
+
diff --git a/gtkdoc-mktmpl b/gtkdoc-mktmpl
new file mode 100755
index 0000000..00dcba5
--- /dev/null
+++ b/gtkdoc-mktmpl
@@ -0,0 +1,466 @@
+#!/usr/bin/perl -w
+#
+# This creates all the empty documents which we then type the descritions
+# into. It doesn't overwrite files, to make sure we don't accidentally lost
+# work.
+#
+# Currently if GTK is updated I run this using a different $DOCS_OUTPUT_DIR
+# and copy any new function templates into the existing documents.
+# Ideally this script would interleave the new, empty, templates with the
+#
+# The CheckAllDeclarationsOutput function checks that all the declarations
+# which were found with scangtk have been used, and writes unused ones to
+# gXXX-unused.txt, which does make it easier when GTK is updated.
+#
+# Also, I haven't output templates to describe signal handlers yet.
+#
+
+use Getopt::Long;
+
+# Options
+
+# name of documentation module
+my $MODULE;
+my $DOCS_OUTPUT_DIR;
+
+%optctl = (module => \$MODULE,
+ 'output-dir' => \$DOCS_OUTPUT_DIR);
+GetOptions(\%optctl, "module=s", "output-dir:s");
+
+$ROOT_DIR = ".";
+
+# All the files are written in subdirectories beneath here.
+$DOCS_OUTPUT_DIR = $DOCS_OUTPUT_DIR ? $DOCS_OUTPUT_DIR : "$ROOT_DIR/tmpl";
+
+# This file is output from a C program I wrote, based on some code in Glade.
+$GTK_SIGNALS_FILE = "$ROOT_DIR/$MODULE.signals";
+
+&ReadSignalsFile;
+
+# Create the top output directory if it doens't exist.
+if (! -e $DOCS_OUTPUT_DIR) {
+ mkdir ("$DOCS_OUTPUT_DIR", 0777)
+ || die "Can't create directory: $DOCS_OUTPUT_DIR";
+}
+
+&ReadDeclarationsFile ("$ROOT_DIR/$MODULE-decl.txt", 0);
+if (-f "$ROOT_DIR/$MODULE-overrides.txt") {
+ &ReadDeclarationsFile ("$ROOT_DIR/$MODULE-overrides.txt", 1);
+}
+&OutputDocs ("$ROOT_DIR/$MODULE-sections.txt");
+&CheckAllDeclarationsOutput;
+
+# This reads in a file containing the function/macro/enum etc. declarations.
+#
+# Note that in some cases there are several declarations with the same name,
+# e.g. for conditional macros. In this case we set a flag in the
+# %DeclarationConditional hash so the declaration is not shown in the docs.
+#
+# If a macro and a function have the same name, e.g. for gtk_object_ref,
+# the function declaration takes precedence.
+#
+# Some opaque structs are just declared with 'typedef _name name;' in which
+# case the declaration may be empty. The structure may have been
+# found later in the header, so that overrides the empty declaration.
+#
+
+sub ReadDeclarationsFile {
+ local ($file, $override) = @_;
+
+ if ($override == 0) {
+ %Declarations = ();
+ %DeclarationTypes = ();
+ %DeclarationConditional = ();
+ %DeclarationOutput = ();
+ }
+
+ open (INPUT, $file)
+ || die "Can't open $file";
+ $declaration_type = "";
+ while (<INPUT>) {
+ if (!$declaration_type) {
+ if (m/^<([^>]+)>/) {
+ $declaration_type = $1;
+ $declaration_name = "";
+# print "Found declaration: $declaration_type\n";
+ $declaration = "";
+ }
+ } else {
+ if (m%^<NAME>(.*)</NAME>%) {
+ $declaration_name = $1;
+ } elsif (m%^</$declaration_type>%) {
+# print "Found end of declaration: $declaration_name\n";
+ # Check that the declaration has a name
+ if ($declaration_name eq "") {
+ print "ERROR: $declaration_type has no name $file:$.\n";
+ }
+
+ # Check if the symbol is already defined.
+ if (defined ($Declarations{$declaration_name})
+ && $override == 0) {
+ # Function declarations take precedence.
+ if ($DeclarationTypes{$declaration_name} eq 'FUNCTION') {
+ # Ignore it.
+ } elsif ($declaration_type eq 'FUNCTION') {
+ $Declarations{$declaration_name} = $declaration;
+ $DeclarationTypes{$declaration_name} = $declaration_type;
+ } elsif ($DeclarationTypes{$declaration_name}
+ eq $declaration_type) {
+ # If the existing declaration is empty override it.
+ if ($declaration_type eq 'STRUCT') {
+ if ($Declarations{$declaration_name} =~ m/^\s*$/) {
+ $Declarations{$declaration_name} = $declaration;
+ } elsif ($declaration =~ m/^\s*$/) {
+ # Ignore an empty declaration.
+ } else {
+ print "WARNING: Structure has multiple definitions: $declaration_name\n";
+ }
+
+ } else {
+ # set flag in %DeclarationConditional hash for
+ # multiply defined macros/typedefs.
+ $DeclarationConditional{$declaration_name} = 1;
+ }
+ } else {
+ print "ERROR: $declaration_name has multiple definitions\n";
+ }
+ } else {
+ $Declarations{$declaration_name} = $declaration;
+ $DeclarationTypes{$declaration_name} = $declaration_type;
+ }
+ $declaration_type = "";
+ } else {
+ $declaration .= $_;
+ }
+ }
+ }
+ close (INPUT);
+}
+
+
+# This reads in an existing file which contains information on all GTK signals.
+# It creates the arrays @SignalNames and @SignalPrototypes containing info on
+# the signals. The first line of the SignalPrototype is the return type of
+# the signal handler. The remaining lines are the parameters passed to it.
+# The last parameter, "gpointer user_data" is always the same so is not
+# included.
+sub ReadSignalsFile {
+ @SignalObjects = ();
+ @SignalNames = ();
+ @SignalReturns = ();
+ @SignalPrototypes = ();
+
+ if (!open (INPUT, $GTK_SIGNALS_FILE)) {
+ warn "Can't open $GTK_SIGNALS_FILE - skipping signals\n";
+ return;
+ }
+ $in_signal = 0;
+ while (<INPUT>) {
+ if (!$in_signal) {
+ if (m/^<SIGNAL>/) {
+ $in_signal = 1;
+ $signal_object = "";
+ $signal_name = "";
+ $signal_returns = "";
+ $signal_prototype = "";
+ }
+ } else {
+ if (m/^<NAME>(.*)<\/NAME>/) {
+ $signal_name = $1;
+ if ($signal_name =~ m/^(.*)::(.*)$/) {
+ $signal_object = $1;
+ $signal_name = $2;
+# print "Found signal: $signal_name\n";
+ } else {
+ print "Invalid signal name: $signal_name\n";
+ }
+ } elsif (m/^<RETURNS>(.*)<\/RETURNS>/) {
+ $signal_returns = $1;
+ } elsif (m%^</SIGNAL>%) {
+# print "Found end of signal: ${signal_object}::${signal_name}\nReturns: ${signal_returns}\n${signal_prototype}";
+ push (@SignalObjects, $signal_object);
+ push (@SignalNames, $signal_name);
+ push (@SignalReturns, $signal_returns);
+ push (@SignalPrototypes, $signal_prototype);
+ $in_signal = 0;
+ } else {
+ $signal_prototype .= $_;
+ }
+ }
+ }
+ close (INPUT);
+}
+
+
+
+# This collects the output for each section of the docs, and outputs
+# each file when the end of the section is found.
+sub OutputDocs {
+ local ($file) = $_[0];
+ print "Reading: $file\n";
+ open (INPUT, $file)
+ || die "Can't open $file";
+ $title = "";
+ my ($subsection) = "";
+ while (<INPUT>) {
+ if (m/^#/) {
+ next;
+
+ } elsif (m/^<SECTION>/) {
+ $DOCFILE = "";
+
+ } elsif (m/^<SUBSECTION>/) {
+ next;
+
+ } elsif (m/^<TITLE>(.*)<\/TITLE>/) {
+ $title = $1;
+# print "Section: $title\n";
+
+ # We don't want warnings if object & class structs aren't used.
+ $DeclarationOutput{$title} = 1;
+ $DeclarationOutput{"${title}Class"} = 1;
+
+ } elsif (m/^<FILE>(.*)<\/FILE>/) {
+ $file = $1;
+
+ } elsif (m/^<NAME>(.*)<\/NAME>/) {
+ $subsection = $1;
+
+
+ } elsif (m/^<\/SECTION>/) {
+ if ($title eq "") {
+ $title = $file;
+ }
+# print "End of section: $title\n";
+
+ $file =~ s/\s/_/g;
+ $file .= ".sgml";
+
+ &OutputDocsFile ($file, $title);
+
+ $title = "";
+ $subsection = "";
+
+ } elsif (m/^(\S+)/) {
+ $symbol = $1;
+# print " Symbol: $symbol\n";
+
+ $declaration = $Declarations{$1};
+ if (defined ($declaration)) {
+ # We don't want templates for standard macros/functions of
+ # GtkObjects.
+ if ($subsection ne "Standard") {
+ &OutputDeclaration ($symbol, $declaration);
+ }
+
+ # Note that the declaration has been output.
+ $DeclarationOutput{$symbol} = 1;
+
+ if ($declaration eq '##conditional##') {
+# print "Conditional $DeclarationTypes{$symbol}\n";
+ }
+ } else {
+ print "WARNING: No declaration for: $1\n";
+ }
+ }
+ }
+ close (INPUT);
+}
+
+
+# This steps through all the declarations that were loaded, and makes sure
+# that each one has been output, by checking the corresponding flag in the
+# %DeclarationOutput hash. It is intended to check that any new declarations
+# in new version of GTK get added to the gXXX-sections.txt file.
+sub CheckAllDeclarationsOutput {
+ $NumUnused = 0;
+ open (UNUSED, ">$ROOT_DIR/$MODULE-unused.txt")
+ || die "Can't open $ROOT_DIR/$MODULE-unused.txt";
+ foreach $symbol (keys (%Declarations)) {
+ if (!defined ($DeclarationOutput{$symbol})) {
+ print (UNUSED "$symbol\n");
+ $NumUnused++;
+ }
+ }
+ close (UNUSED);
+ if ($NumUnused != 0) {
+ print <<EOF;
+=============================================================================
+WARNING: $NumUnused unused declarations.
+ These can be found in $MODULE-unused.txt.
+ They should be added to $MODULE-sections.txt in the appropriate place.
+=============================================================================
+EOF
+ }
+}
+
+
+sub OutputDeclaration {
+ local ($symbol, $declaration) = @_;
+
+ $type = $DeclarationTypes {$symbol};
+# print "Outputting $type: $symbol\n";
+
+ $DOCFILE .= <<EOF;
+<!-- ##### $type $symbol ##### -->
+<para>
+
+</para>
+
+EOF
+
+ # For functions, function typedefs and macros, we output the arguments.
+ # For functions and function typedefs we also output the return value.
+ if ($type eq "FUNCTION" || $type eq "USER_FUNCTION") {
+ # Take out the return type
+ $declaration =~ s/<RETURNS>\s*(const\s+|unsigned\s+)*(\w+)\s*(\**)\s*<\/RETURNS>\n//;
+ $ret_type = $2;
+
+ $param_num = 0;
+ while ($declaration ne "") {
+ if ($declaration =~ s/^[\s,]+//) {
+ # skip whitespace and commas
+ next;
+
+ } elsif ($declaration =~ s/^void\s*[,\n]//) {
+ if ($param_num != 0) {
+ print "WARNING: void used as parameter in function $symbol\n";
+ }
+
+ } elsif ($declaration =~ s/^...\s*[,\n]//) {
+ $DOCFILE .= "\@Varargs: \n";
+
+ # allow alphanumerics, '_', '[' & ']' in param names
+ } elsif ($declaration =~ s/^(const\s+|unsigned\s+)*(struct\s+)?(\w+)\s*(\**)\s*(const\s+)?(\**)?\s*(\w+)?\s*(\[\])?\s*[,\n]//) {
+ if (defined($7)) {
+ $name = $7;
+ } else {
+ $name = "Param" . ($j + 1);
+ }
+ $DOCFILE .= "\@$name: \n";
+
+ # Try to match parameters which are functions.
+ } elsif ($declaration =~ s/^(const\s+|unsigned\s+)*(struct\s+)?(\w+)\s*(\**)\s*(const\s+)?\(\s*\*\s*(\w+)\s*\)\s*\(([^)]*)\)\s*[,\n]//) {
+ $name = $6;
+ $DOCFILE .= "\@$name: \n";
+
+ } else {
+ print "###Can't parse args for function $symbol: $declaration\n";
+ last;
+ }
+ $param_num++;
+ }
+
+
+ if ($ret_type ne "void") {
+ $DOCFILE .= "\@Returns: \n";
+ }
+ }
+
+ if ($type eq "MACRO") {
+ if ($declaration =~ m/^\s*#\s*define\s+\w+\(([^\)]*)\)/) {
+ $args = $1;
+ @params = split ("[,\n]", $args);
+ for ($j = 0; $j <= $#params; $j++) {
+ $param = $params[$j];
+ $param =~ s/^\s+//;
+ $param =~ s/\s*$//;
+ if ($param =~ m/^\s*$/) { next; }
+ $DOCFILE .= "\@$param: \n";
+ }
+ }
+ }
+ $DOCFILE .= "\n";
+}
+
+
+# This outputs one empty template file.
+# If the file already exists it will just return.
+sub OutputDocsFile {
+ local ($file, $title) = @_;
+
+ if (-e "$DOCS_OUTPUT_DIR/$MODULE" && ! -d _) {
+ die "$DOCS_OUTPUT_DIR/$MODULE exists and is not a directory";
+ }
+ if (! -e _) {
+ mkdir ("$DOCS_OUTPUT_DIR/$MODULE", 0777)
+ || die "Can't create directory: $DOCS_OUTPUT_DIR/$MODULE";
+ }
+
+ # Don't overwrite existing files.
+ if (-f "$DOCS_OUTPUT_DIR/$file") {
+ print "$DOCS_OUTPUT_DIR/$file already exists - skipping.\n";
+ return;
+ }
+
+ open (OUTPUT, ">$DOCS_OUTPUT_DIR/$file")
+ || die "Can't create $DOCS_OUTPUT_DIR/$file";
+
+ print (OUTPUT <<EOF);
+<!-- ##### SECTION Title ##### -->
+$title
+
+<!-- ##### SECTION Short_Description ##### -->
+
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+EOF
+
+ print (OUTPUT $DOCFILE);
+
+ &OutputSignalTemplates ($title);
+
+ close (OUTPUT);
+}
+
+
+sub OutputSignalTemplates {
+ local ($title) = $_[0];
+
+ $SIGS = "";
+ for ($i = 0; $i <= $#SignalObjects; $i++) {
+ if ($SignalObjects[$i] eq $title) {
+# print "Found signal: $SignalObjects[$i]\n";
+
+ $SIGS .= <<EOF;
+<!-- ##### SIGNAL $SignalObjects[$i]::$SignalNames[$i] ##### -->
+<para>
+
+</para>
+
+EOF
+
+ @params = split ("[,\n]", $SignalPrototypes[$i]);
+ for ($j = 0; $j <= $#params; $j++) {
+ $param = $params[$j];
+ $param =~ s/^\s+//;
+ $param =~ s/\s*$//;
+ if ($param =~ m/^\s*$/) { next; }
+ if ($param =~ m/^void$/) { next; }
+
+ if ($param =~ m/^\s*(\w+)\s*(\**)\s*([\w\[\]]+)?\s*$/) {
+ if (defined($3)) {
+ $name = $3;
+ } else {
+ $name = "Param" . ($j + 1);
+ }
+ if ($j == 0) {
+ $SIGS .= "\@$name: the object which received the signal.\n";
+ } else {
+ $SIGS .= "\@$name: \n";
+ }
+ }
+ }
+
+ if ($SignalReturns[$i] ne "void") {
+ $SIGS .= "\@Returns: \n";
+ }
+ $SIGS .= "\n";
+ }
+ }
+ print (OUTPUT $SIGS);
+}
diff --git a/gtkdoc-scan b/gtkdoc-scan
new file mode 100755
index 0000000..277e59e
--- /dev/null
+++ b/gtkdoc-scan
@@ -0,0 +1,381 @@
+#!/usr/bin/perl -w
+#
+# Perl script to extract declarations of functions, macros, enums, structs and
+# unions from header files to be used for generating DocBook documentation.
+#
+# It outputs all declarations found to a file named '$MODULE-decl.txt', and the
+# list of decarations to another file '$MODULE-decl-list.txt'.
+# This second list file is copied to '$MODULE-sections.txt' and organized into
+# sections ready to output the SGML pages.
+#
+# It is called with a module name, an optional output directory, and the
+# header files to scan.
+#
+
+use Getopt::Long;
+
+# Options
+
+# name of documentation module
+my $MODULE;
+my $OUTPUT_DIR;
+
+%optctl = (module => \$MODULE,
+ 'output-dir' => \$OUTPUT_DIR);
+GetOptions(\%optctl, "module=s", "output-dir:s");
+
+$OUTPUT_DIR = $OUTPUT_DIR ? $OUTPUT_DIR : ".";
+
+if (!-d ${OUTPUT_DIR}) {
+ mkdir($OUTPUT_DIR, 0755) || die "Cannot create $OUTPUT_DIR: $!";
+}
+
+# Backup existing files
+if (-f "${OUTPUT_DIR}/$MODULE-decl-list.txt") {
+ rename ("${OUTPUT_DIR}/$MODULE-decl-list.txt",
+ "${OUTPUT_DIR}/$MODULE-decl-list.bak");
+}
+
+if (-f "${OUTPUT_DIR}/$MODULE-decl.txt") {
+ rename ("${OUTPUT_DIR}/$MODULE-decl.txt",
+ "${OUTPUT_DIR}/$MODULE-decl.bak");
+}
+
+open (LIST, ">${OUTPUT_DIR}/$MODULE-decl-list.txt")
+ || die "Can't open ${OUTPUT_DIR}/$MODULE-decl-list.txt";
+open (TYPES, ">${OUTPUT_DIR}/$MODULE-decl.txt")
+ || die "Can't open ${OUTPUT_DIR}/$MODULE-decl.txt";
+
+$main_list = $object_list = "";
+
+for $file (@ARGV) {
+ my $file_basename;
+ if ($file =~ m/^.*[\/\\](.*)\.h$/) {
+ $file_basename = $1;
+ } else {
+ print "WARNING: Can't find basename of file $file\n";
+ $file_basename = $file;
+ }
+
+ # We split the output into two parts - GtkObject subclasses and everything
+ # else, so that all GtkObjects/Widgets are kept together.
+ my ($list, $is_object) = &ScanHeader($file);
+ if ($is_object) {
+ $object_list .= "<SECTION>\n<FILE>$file_basename</FILE>\n$list</SECTION>\n";
+ } else {
+ $main_list .= "<SECTION>\n<FILE>$file_basename</FILE>\n$list</SECTION>\n";
+ }
+}
+
+print LIST $object_list, $main_list;
+close (LIST);
+close (TYPES);
+
+# This scans a header file, looking for declarations of functions, macros,
+# typedefs, structs and unions, which it outputs to the TYPES file.
+# It returns the list of declarations found, and a boolean which is 1 if the
+# header file is describing a GtkObject subclass.
+sub ScanHeader {
+ my ($input_file) = @_;
+
+# print "Scanning: $input_file\n";
+ $list = "";
+ @objects = ();
+
+ if (! -f $input_file) {
+ print "File doesn't exist: $input_file\n";
+ return ("", 0);
+ }
+
+ open(INPUT, $input_file)
+ || die "Couldn't open file: $input_file";
+ my ($in_declaration) = "";
+ my ($previous_line) = "";
+ my ($first_macro) = 1;
+ my ($in_comment) = 0;
+ while(<INPUT>) {
+
+ # Skip to the end of the current comment.
+ if ($in_comment) {
+ if (m%\*/%) {
+ $in_comment = 0;
+ }
+ next;
+ }
+
+ # Look for a widget class to use as the section title.
+ # Style isn't really an object.
+ if (m/^struct\s+_(Gtk\S+|Gnome\S+)Class/) {
+ if ($1 ne 'GtkStyle') {
+ $list .= "<TITLE>$1</TITLE>\n";
+ }
+ }
+
+ if (!$in_declaration) {
+
+ # Skip top-level comments.
+ if (s%^\s*/\*%%) {
+ if (m%\*/%) {
+# print "Found one-line comment: $_";
+ } else {
+ $in_comment = 1;
+# print "Found start of comment: $_";
+ }
+ next;
+ }
+
+ if (m/^\s*#\s*define\s+(\w+)/) {
+ $macro = $1;
+ # We assume all macros which start with '_' are private, but
+ # we accept '_' itself which is the standard gettext macro.
+ # We also try to skip the header #ifdef/#define macro at the
+ # top of most header files.
+ # We also try to skip the first macro if it looks like the
+ # standard #ifndef HEADER_FILE #define HEADER_FILE etc.
+ # And we only want TRUE & FALSE defined in GLib.
+ if (($macro !~ m/^_/
+ && ($previous_line !~ m/#ifndef\s+$macro/
+ || $first_macro == 0)
+ && (($macro ne 'TRUE' && $macro ne 'FALSE')
+ || $MODULE eq 'glib'))
+ || $macro eq "_") {
+ $args = $_;
+ $in_declaration = "macro";
+ }
+ $first_macro = 0;
+
+ } elsif (m/^typedef\s+((const\s+)?\w+)\s*(\**)\s*\(\*\s*(\w+)\)\s*\(/) {
+ $ret_type = $1;
+ $modifier = $3;
+ $function = $4;
+ $args = $';
+ $in_declaration = "user_function";
+
+ } elsif (s/^enum\s+_(\w+)\s+\{/enum $1 {/) {
+ $enum = $1;
+# print "DEBUG: plain enum: $enum\n";
+ $args = $_;
+ $in_declaration = "enum";
+
+ } elsif (m/^typedef\s+enum\s+_(\w+)\s+\1\s*;/) {
+# print "DEBUG: skipping enum typedef: $1\n";
+
+ } elsif (m/^typedef\s+enum/) {
+ $enum = "";
+ $args = $_;
+ $in_declaration = "enum";
+
+ } elsif (m/^typedef\s+struct\s+_(\w+)\s+\1\s*;/) {
+# print "DEBUG: struct typedef: $1\n";
+ &AddSymbolToList ($1);
+ # This could be an opaque data structure, so we output an
+ # empty declaration. If the structure is actually found that
+ # will override this.
+ print TYPES "<STRUCT>\n<NAME>$1</NAME>\n</STRUCT>\n";
+
+ } elsif (m/^typedef\s+struct\s*{/) {
+ $struct = "";
+ $args = $_;
+ $level = 0;
+ $in_declaration = "struct";
+
+ } elsif (s/^struct\s+_(\w+)/struct $1/) {
+ $struct = $1;
+ $args = $_;
+ # We skip object structs
+ if ($struct =~ m/^(Gtk\S+|Gnome\S+)Class/
+ && $1 ne 'GtkStyle') {
+# print "Found class: $1\n";
+ push (@objects, $1);
+ } else {
+ $level = 0;
+ $in_declaration = "struct";
+ }
+
+ } elsif (s/^union\s+_(\w+)/union $1/) {
+ $union = $1;
+ $args = $_;
+ $in_declaration = "union";
+
+ } elsif (m/^typedef\s+(.+[\s\*])(\w\S*);/) {
+ if ($1 !~ m/^struct\s/ && $1 !~ m/^union\s/) {
+# print "Found typedef: $_";
+ &AddSymbolToList ($2);
+ print TYPES "<TYPEDEF>\n<NAME>$2</NAME>\n$_</TYPEDEF>\n";
+ }
+ } elsif (m/^typedef\s+/) {
+# print "Skipping typedef: $_";
+
+ } elsif (m/^extern\s+/) {
+# print "Skipping extern: $_";
+
+ # We assume that functions which start with '_' are private, so
+ # we skip them.
+ } elsif (m/^\s*(G_INLINE_FUNC)?\s*((const\s+|unsigned\s+)*\w+)(\s\*+|\*+|\s)\s*([A-Za-z]\w*)\s*\(/) {
+ $ret_type = $2;
+ $modifier = $4;
+ $function = $5;
+ $args = $';
+
+ # Don't want typedefs
+ if ($ret_type ne 'typedef') {
+# print "Function: $function, Returns: ${ret_type}$modifier\n";
+ $in_declaration = "function";
+ }
+
+ # Try to catch function declarations which have the return type on
+ # the previous line. But we don't want to catch complete functions
+ # which have been declared G_INLINE_FUNC, e.g. g_bit_nth_lsf in
+ # glib, or 'static inline' functions.
+ } elsif (m/^([A-Za-z]\w*)\s*\(/) {
+ $function = $1;
+ $args = $';
+ if ($previous_line !~ m/^\s*G_INLINE_FUNC/
+ && $previous_line !~ m/^\s*static\s+inline/) {
+ if ($previous_line =~ m/^((const\s*)?\w+)(\s*\*+)?/) {
+ $ret_type = $1;
+ $modifier = defined ($3) ? $3 : "";
+# print "Function: $function, Returns: ${ret_type}$modifier\n";
+ $in_declaration = "function";
+ }
+ }
+ }
+ } else {
+ $args .= $_;
+ }
+
+ # Note that sometimes functions end in ') G_GNUC_PRINTF (2, 3);'.
+ if ($in_declaration eq 'function') {
+ if ($args =~ s/\)\s*(G_GNUC_.*)?;.*$//) {
+ $args =~ s/^\s+//;
+ $args =~ s/\n\s+/\n/g;
+ $args =~ s/\s+$//;
+ $args =~ s/\s+\n/\n/g;
+ $args =~ s%/\*.*?\*/%%gs; # remove comments
+ $ret_type =~ s%/\*.*?\*/%%g; # remove comments
+ &AddSymbolToList ($function);
+ print TYPES "<FUNCTION>\n<NAME>$function</NAME>\n<RETURNS>$ret_type $modifier</RETURNS>\n$args\n</FUNCTION>\n";
+ $in_declaration = "";
+ }
+ }
+
+ if ($in_declaration eq 'user_function') {
+ if ($args =~ s/\).*$//) {
+ &AddSymbolToList ($function);
+ print TYPES "<USER_FUNCTION>\n<NAME>$function</NAME>\n<RETURNS>$ret_type $modifier</RETURNS>\n$args</USER_FUNCTION>\n";
+ $in_declaration = "";
+ }
+ }
+
+ if ($in_declaration eq 'macro') {
+ if ($args !~ m/\\\s*$/) {
+ &AddSymbolToList ($macro);
+ print TYPES "<MACRO>\n<NAME>$macro</NAME>\n$args</MACRO>\n";
+ $in_declaration = "";
+ }
+ }
+
+ if ($in_declaration eq 'enum') {
+ if ($args =~ m/\}\s*(\w+)?;\s*$/) {
+ if ($enum eq "") {
+ $enum = $1;
+ }
+ &AddSymbolToList ($enum);
+ print TYPES "<ENUM>\n<NAME>$enum</NAME>\n$args</ENUM>\n";
+ $in_declaration = "";
+ }
+ }
+
+ # We try to handle nested stucts/unions, but brackets in comments
+ # may cause problems.
+ if ($in_declaration eq 'struct') {
+ if ($level <= 1 && $args =~ m/\}\s*(\w*);\s*$/) {
+ if ($struct eq "") {
+ $struct = $1;
+ }
+ &AddSymbolToList ($struct);
+ print TYPES "<STRUCT>\n<NAME>$struct</NAME>\n$args</STRUCT>\n";
+ $in_declaration = "";
+ } else {
+ if (m/\{/) {
+ $level++;
+# print "DEBUG: level: $level\n";
+ }
+ if (m/\}/) {
+ $level--;
+# print "DEBUG: level: $level\n";
+ }
+ }
+ }
+
+ if ($in_declaration eq 'union') {
+ if ($args =~ m/\}\s*;\s*$/) {
+ &AddSymbolToList ($union);
+ print TYPES "<UNION>\n<NAME>$union</NAME>\n$args</UNION>\n";
+ $in_declaration = "";
+ }
+ }
+
+ $previous_line = $_;
+ }
+ close(INPUT);
+
+ # Take out any object structs
+ foreach $object (@objects) {
+ $list =~ s/^$object\n//m;
+ $list =~ s/^${object}Class\n//m;
+ }
+
+
+ # Try to separate the standard macros and function.
+ # FIXME: GTK specific.
+ my ($class) = "";
+ my ($standard_decl) = "";
+ if ($list =~ m/^GTK_IS_(.*)_CLASS/m) {
+ $class = $1;
+ } elsif ($list =~ m/^GTK_IS_(.*)/m) {
+ $class = $1;
+ } elsif ($list =~ m/^GNOME_IS_(.*)_CLASS/m) {
+ $class = $1;
+ } elsif ($list =~ m/^GNOME_IS_(.*)/m) {
+ $class = $1;
+ }
+
+ if ($class ne "") {
+# print "Found class: $class\n";
+
+ if ($list =~ s/^GTK_$class\n//m) { $standard_decl .= $&; }
+ if ($list =~ s/^GTK_IS_$class\n//m) { $standard_decl .= $&; }
+ if ($list =~ s/^GTK_TYPE_$class\n//m) { $standard_decl .= $&; }
+ if ($list =~ s/^gtk_.*_get_type\n//m) { $standard_decl .= $&; }
+ if ($list =~ s/^GTK_${class}_CLASS\n//m) { $standard_decl .= $&; }
+ if ($list =~ s/^GTK_IS_${class}_CLASS\n//m) { $standard_decl .= $&; }
+
+ if ($list =~ s/^GNOME_$class\n//m) { $standard_decl .= $&; }
+ if ($list =~ s/^GNOME_IS_$class\n//m) { $standard_decl .= $&; }
+ if ($list =~ s/^GNOME_TYPE_$class\n//m) { $standard_decl .= $&; }
+ if ($list =~ s/^gnome_.*_get_type\n//m) { $standard_decl .= $&; }
+ if ($list =~ s/^GNOME_${class}_CLASS\n//m) { $standard_decl .= $&; }
+ if ($list =~ s/^GNOME_IS_${class}_CLASS\n//m) { $standard_decl .= $&; }
+
+ if ($standard_decl ne "") {
+ $list .= "<SUBSECTION>\n<NAME>Standard</NAME>\n$standard_decl";
+ }
+ return ($list, 1);
+ } else {
+ return ($list, 0);
+ }
+}
+
+
+# This adds the symbol to the list of declarations, but only if it is not
+# already in the list.
+sub AddSymbolToList {
+ my ($symbol) = @_;
+
+ if ($list =~ m/\b\Q$symbol\E\b/) {
+# print "Symbol $symbol already in list. skipping\n";
+ return;
+ }
+ $list .= "$symbol\n";
+}
diff --git a/gtkdoc-scanobj b/gtkdoc-scanobj
new file mode 100755
index 0000000..542c08b
--- /dev/null
+++ b/gtkdoc-scanobj
@@ -0,0 +1,680 @@
+#!/usr/bin/perl -w
+#
+# This gets information about object heirarchies and signals
+# by compiling a small C program. CFLAGS and LDFLAGS must be
+# set appropriately before running this script.
+#
+
+use Getopt::Long;
+
+# Options
+
+# name of documentation module
+my $MODULE;
+my $OUTPUT_DIR;
+
+%optctl = (module => \$MODULE,
+ types => \$TYPES_FILE);
+
+GetOptions(\%optctl, "module=s", "types:s");
+
+$TYPES_FILE = $TYPES_FILE ? $TYPES_FILE : "$MODULE.types";
+
+open TYPES, $TYPES_FILE || die "Cannot open $TYPES_FILE: $!\n";
+open OUTPUT, ">$MODULE-scan.c" || die "Cannot open $MODULE-scan.c: $!\n";
+
+# write a C program to scan the types
+
+$includes = "";
+@types = ();
+
+for (<TYPES>) {
+ if (/^#include/) {
+ $includes .= $_;
+ } elsif (/^%/) {
+ next;
+ } elsif (/^\s*$/) {
+ next;
+ } else {
+ chomp;
+ push @types, $_;
+ }
+}
+
+$ntypes = @types + 1;
+
+print OUTPUT <<EOT;
+#include <string.h>
+#include <stdio.h>
+
+$includes
+GtkType object_types[$ntypes];
+
+GtkType *
+get_object_types ()
+{
+ gint i = 0;
+EOT
+
+for (@types) {
+ print OUTPUT " object_types[i++] = $_ ();\n";
+}
+
+print OUTPUT <<EOT;
+ object_types[i] = 0;
+
+ return object_types;
+}
+
+/*
+ * This outputs signal prototypes in a form which can be read by mkdocbook.pl
+ * It also outputs the widget hierarchy.
+ */
+
+/* The output files */
+gchar *signals_filename = "$MODULE.signals";
+gchar *hierarchy_filename = "$MODULE.hierarchy";
+
+
+extern GtkType* get_object_types();
+
+/* These are used for outputting signal handler prototypes. */
+#define GB_PARAM_INDENT 40
+#define GB_PARAM_TYPE_WIDTH 16
+
+void gb_widgets_init ();
+void output_signals ();
+void output_widget_signals (FILE *fp, GtkType object_type);
+void output_widget_signal (FILE *fp, GtkType object_type,
+ gchar *object_class_name, guint signal_id);
+static gchar * get_type_name (GtkType type, gboolean * is_pointer);
+static gchar * get_gdk_event (const gchar * signal_name);
+static gchar ** lookup_signal_arg_names (gchar * type,
+ const gchar * signal_name);
+
+static void output_widget_hierarchy ();
+static void output_hierarchy (FILE *fp,
+ GtkType type,
+ gint level);
+
+
+int
+main (int argc, char *argv[])
+{
+ gtk_init (&argc, &argv);
+
+ output_signals ();
+ output_widget_hierarchy ();
+
+ return 0;
+}
+
+
+void
+output_signals ()
+{
+ FILE *fp;
+ GtkType *object_types;
+ gint i;
+
+ fp = fopen (signals_filename, "w");
+ if (fp == NULL)
+ {
+ g_warning ("Couldn't open output file: %s", signals_filename);
+ return;
+ }
+
+ object_types = get_object_types();
+
+ for (i = 0; object_types[i]; i++)
+ output_widget_signals (fp, object_types[i]);
+
+ fclose (fp);
+}
+
+
+/* This outputs all the signals of one widget. */
+void
+output_widget_signals (FILE *fp, GtkType object_type)
+{
+ GtkObjectClass *class;
+ gchar *object_class_name;
+ guint sig;
+
+ class = gtk_type_class (object_type);
+ if (!class || class->nsignals == 0)
+ return;
+
+ object_class_name = gtk_type_name (object_type);
+
+ for (sig = 0; sig < class->nsignals; sig++)
+ {
+ if (!class->signals[sig])
+ {
+ /*g_print ("Signal slot [%u] is empty\n", sig);*/
+ continue;
+ }
+
+ output_widget_signal (fp, object_type, object_class_name,
+ class->signals[sig]);
+ }
+}
+
+
+/* This outputs one signal. */
+void
+output_widget_signal (FILE *fp,
+ GtkType object_type,
+ gchar *object_name,
+ guint signal_id)
+{
+ GtkSignalQuery *query_info;
+ gchar *ret_type, *pos, *type_name, *arg_name, *object_arg, *object_arg_start;
+ gboolean is_pointer;
+ gchar ret_type_buffer[1024], buffer[1024];
+ gint i, param;
+ gchar **arg_names;
+ gint param_num, widget_num, event_num, callback_num;
+ gint *arg_num;
+ gchar signal_name[128];
+
+
+ /* g_print ("Object: %s Type: %i Signal: %u\n", object_name, object_type,
+ signal_id);*/
+
+ param_num = 1;
+ widget_num = event_num = callback_num = 0;
+
+ /* Output empty signal handler. */
+ query_info = gtk_signal_query (signal_id);
+ if (query_info == NULL)
+ {
+ g_warning ("Couldn't query signal");
+ return;
+ }
+
+ /* Output the return type and function name. */
+ ret_type = get_type_name (query_info->return_val, &is_pointer);
+ sprintf (ret_type_buffer, "%s%s", ret_type, is_pointer ? "*" : "");
+
+ /* Output the signal object type and the argument name. We assume the
+ type is a pointer - I think that is OK. We remove "Gtk" and convert
+ to lower case for the argument name. */
+ pos = buffer;
+ sprintf (pos, "%s ", object_name);
+ pos += strlen (pos);
+
+ object_arg = (!strncmp (object_name, "Gtk", 3)) ? object_name + 3
+ : object_name;
+ object_arg_start = pos;
+ sprintf (pos, "*%s\n", object_arg);
+ pos += strlen (pos);
+ g_strdown (object_arg_start);
+ if (!strcmp (object_arg_start, "widget"))
+ widget_num++;
+
+ /* Convert signal name to use underscores rather than dashes '-'. */
+ strcpy (signal_name, query_info->signal_name);
+ for (i = 0; signal_name[i]; i++)
+ {
+ if (signal_name[i] == '-')
+ signal_name[i] = '_';
+ }
+
+ /* Output the signal parameters. */
+ arg_names = lookup_signal_arg_names (object_name, signal_name);
+
+ for (param = 0; param < query_info->nparams; param++)
+ {
+ if (arg_names)
+ {
+ sprintf (pos, "%s\n", arg_names[param]);
+ pos += strlen (pos);
+ }
+ else
+ {
+ type_name = get_type_name (query_info->params[param], &is_pointer);
+
+ /* Most arguments to the callback are called "arg1", "arg2", etc.
+ GdkWidgets are called "widget", "widget2", ...
+ GdkEvents are called "event", "event2", ...
+ GtkCallbacks are called "callback", "callback2", ... */
+ if (!strcmp (type_name, "GtkWidget"))
+ {
+ arg_name = "widget";
+ arg_num = &widget_num;
+ }
+ else if (!strcmp (type_name, "GdkEvent"))
+ {
+ type_name = get_gdk_event (signal_name);
+ arg_name = "event";
+ arg_num = &event_num;
+ is_pointer = TRUE;
+ }
+ else if (!strcmp (type_name, "GtkCallback")
+ || !strcmp (type_name, "GtkCCallback"))
+ {
+ arg_name = "callback";
+ arg_num = &callback_num;
+ }
+ else
+ {
+ arg_name = "arg";
+ arg_num = &param_num;
+ }
+ sprintf (pos, "%s ", type_name);
+ pos += strlen (pos);
+
+ if (!arg_num || *arg_num == 0)
+ sprintf (pos, "%s%s\n", is_pointer ? "*" : " ", arg_name);
+ else
+ sprintf (pos, "%s%s%i\n", is_pointer ? "*" : " ", arg_name,
+ *arg_num);
+ pos += strlen (pos);
+
+ if (arg_num)
+ *arg_num += 1;
+ }
+ }
+
+ fprintf (fp,
+ "<SIGNAL>\n<NAME>%s::%s</NAME>\n<RETURNS>%s</RETURNS>\n%s</SIGNAL>\n\n",
+ object_name, query_info->signal_name, ret_type_buffer, buffer);
+ g_free (query_info);
+}
+
+
+static gchar *
+get_type_name (GtkType type, gboolean * is_pointer)
+{
+ static gchar *GbTypeNames[] =
+ {
+ "char", "gchar",
+ "bool", "gboolean",
+ "int", "gint",
+ "uint", "guint",
+ "long", "glong",
+ "ulong", "gulong",
+ "float", "gfloat",
+ "double", "gdouble",
+ "string", "gchar",
+ "enum", "gint",
+ "flags", "gint",
+ "boxed", "gpointer",
+ "foreign", "gpointer",
+ "callback", "GtkCallback", /* ?? */
+ "args", "gpointer",
+
+ "pointer", "gpointer",
+ "signal", "gpointer",
+ "c_callback", "GtkCallback", /* ?? */
+
+ NULL
+ };
+
+ GtkType parent_type;
+ gchar *type_name, *parent_type_name;
+ gint i;
+
+ *is_pointer = FALSE;
+ type_name = gtk_type_name (type);
+ for (i = 0; GbTypeNames[i]; i += 2)
+ {
+ if (!strcmp (type_name, GbTypeNames[i]))
+ {
+ if (!strcmp (type_name, "string"))
+ *is_pointer = TRUE;
+ return GbTypeNames[i + 1];
+ }
+ }
+
+ for (;;)
+ {
+ parent_type = gtk_type_parent (type);
+ if (parent_type == 0)
+ break;
+ type = parent_type;
+ }
+ parent_type_name = gtk_type_name (type);
+ /*g_print ("Parent type name: %s\n", parent_type_name);*/
+ if (!strcmp (parent_type_name, "GtkObject")
+ || !strcmp (parent_type_name, "boxed")
+ || !strcmp (parent_type_name, "GtkBoxed"))
+ *is_pointer = TRUE;
+
+ return type_name;
+}
+
+
+static gchar *
+get_gdk_event (const gchar * signal_name)
+{
+ static gchar *GbGDKEvents[] =
+ {
+ "button_press_event", "GdkEventButton",
+ "button_release_event", "GdkEventButton",
+ "motion_notify_event", "GdkEventMotion",
+ "delete_event", "GdkEvent",
+ "destroy_event", "GdkEvent",
+ "expose_event", "GdkEventExpose",
+ "key_press_event", "GdkEventKey",
+ "key_release_event", "GdkEventKey",
+ "enter_notify_event", "GdkEventCrossing",
+ "leave_notify_event", "GdkEventCrossing",
+ "configure_event", "GdkEventConfigure",
+ "focus_in_event", "GdkEventFocus",
+ "focus_out_event", "GdkEventFocus",
+ "map_event", "GdkEvent",
+ "unmap_event", "GdkEvent",
+ "property_notify_event", "GdkEventProperty",
+ "selection_clear_event", "GdkEventSelection",
+ "selection_request_event", "GdkEventSelection",
+ "selection_notify_event", "GdkEventSelection",
+ "proximity_in_event", "GdkEventProximity",
+ "proximity_out_event", "GdkEventProximity",
+ "drag_begin_event", "GdkEventDragBegin",
+ "drag_request_event", "GdkEventDragRequest",
+ "drag_end_event", "GdkEventDragRequest",
+ "drop_enter_event", "GdkEventDropEnter",
+ "drop_leave_event", "GdkEventDropLeave",
+ "drop_data_available_event", "GdkEventDropDataAvailable",
+ "other_event", "GdkEventOther",
+ "client_event", "GdkEventClient",
+ "no_expose_event", "GdkEventNoExpose",
+ NULL
+ };
+
+ gint i;
+
+ for (i = 0; GbGDKEvents[i]; i += 2)
+ {
+ if (!strcmp (signal_name, GbGDKEvents[i]))
+ return GbGDKEvents[i + 1];
+ }
+ return "GdkEvent";
+}
+
+
+/* This returns argument names to use for some known GTK signals. */
+/* Note: Could possibly return the types to use as well, since several of
+ them could be better, e.g. "GtkOrientation" instead of "gint". */
+static gchar **
+lookup_signal_arg_names (gchar * type, const gchar * signal_name)
+{
+ /* Each arg array starts with the object type name and the signal name,
+ and then signal arguments follow. Note that the spacing is hardcoded. */
+ static gchar *GbArgTable[][16] =
+ {
+ {"GtkCList", "select_row",
+ "gint row",
+ "gint column",
+ "GdkEventButton *event"},
+ {"GtkCList", "unselect_row",
+ "gint row",
+ "gint column",
+ "GdkEventButton *event"},
+ {"GtkCList", "click_column",
+ "gint column"},
+
+ {"GtkCList", "resize_column",
+ "gint column",
+ "gint width"},
+
+ {"GtkCList", "extend_selection",
+ "GtkScrollType scroll_type",
+ "gfloat position",
+ "gboolean auto_start_selection"},
+ {"GtkCList", "scroll_vertical",
+ "GtkScrollType scroll_type",
+ "gfloat position"},
+ {"GtkCList", "scroll_horizontal",
+ "GtkScrollType scroll_type",
+ "gfloat position"},
+ {"GtkContainer", "focus",
+ "GtkDirectionType direction"},
+ {"GtkCTree", "tree_select_row",
+ "GList *node",
+ "gint column"},
+ {"GtkCTree", "tree_unselect_row",
+ "GList *node",
+ "gint column"},
+
+ {"GtkCTree", "tree_expand",
+ "GList *node"},
+ {"GtkCTree", "tree_collapse",
+ "GList *node"},
+ {"GtkCTree", "tree_move",
+ "GList *node",
+ "GList *new_parent",
+ "GList *new_sibling"},
+ {"GtkCTree", "change_focus_row_expansion",
+ "GtkCTreeExpansionType expansion"},
+
+ {"GtkEditable", "insert_text",
+ "gchar *new_text",
+ "gint new_text_length",
+ "gint *position"},
+ {"GtkEditable", "delete_text",
+ "gint start_pos",
+ "gint end_pos"},
+ {"GtkEditable", "set_editable",
+ "gboolean is_editable"},
+ {"GtkEditable", "move_cursor",
+ "gint x",
+ "gint y"},
+ {"GtkEditable", "move_word",
+ "gint num_words"},
+ {"GtkEditable", "move_page",
+ "gint x",
+ "gint y"},
+ {"GtkEditable", "move_to_row",
+ "gint row"},
+ {"GtkEditable", "move_to_column",
+ "gint column"},
+
+ {"GtkEditable", "kill_char",
+ "gint direction"},
+ {"GtkEditable", "kill_word",
+ "gint direction"},
+ {"GtkEditable", "kill_line",
+ "gint direction"},
+
+
+ {"GtkInputDialog", "enable_device",
+ "gint deviceid"},
+ {"GtkInputDialog", "disable_device",
+ "gint deviceid"},
+
+ {"GtkListItem", "extend_selection",
+ "GtkScrollType scroll_type",
+ "gfloat position",
+ "gboolean auto_start_selection"},
+ {"GtkListItem", "scroll_vertical",
+ "GtkScrollType scroll_type",
+ "gfloat position"},
+ {"GtkListItem", "scroll_horizontal",
+ "GtkScrollType scroll_type",
+ "gfloat position"},
+
+ {"GtkMenuShell", "move_current",
+ "GtkMenuDirectionType direction"},
+ {"GtkMenuShell", "activate_current",
+ "gboolean force_hide"},
+
+
+ {"GtkNotebook", "switch_page",
+ "GtkNotebookPage *page",
+ "gint page_num"},
+ {"GtkStatusbar", "text_pushed",
+ "guint context_id",
+ "gchar *text"},
+ {"GtkStatusbar", "text_popped",
+ "guint context_id",
+ "gchar *text"},
+ {"GtkTipsQuery", "widget_entered",
+ "GtkWidget *widget",
+ "gchar *tip_text",
+ "gchar *tip_private"},
+ {"GtkTipsQuery", "widget_selected",
+ "GtkWidget *widget",
+ "gchar *tip_text",
+ "gchar *tip_private",
+ "GdkEventButton *event"},
+ {"GtkToolbar", "orientation_changed",
+ "GtkOrientation orientation"},
+ {"GtkToolbar", "style_changed",
+ "GtkToolbarStyle style"},
+ {"GtkWidget", "draw",
+ "GdkRectangle *area"},
+ {"GtkWidget", "size_request",
+ "GtkRequisition *requisition"},
+ {"GtkWidget", "size_allocate",
+ "GtkAllocation *allocation"},
+ {"GtkWidget", "state_changed",
+ "GtkStateType state"},
+ {"GtkWidget", "style_set",
+ "GtkStyle *previous_style"},
+
+ {"GtkWidget", "install_accelerator",
+ "gchar *signal_name",
+ "gchar key",
+ "gint modifiers"},
+
+ {"GtkWidget", "add_accelerator",
+ "guint accel_signal_id",
+ "GtkAccelGroup *accel_group",
+ "guint accel_key",
+ "GdkModifierType accel_mods",
+ "GtkAccelFlags accel_flags"},
+
+ {"GtkWidget", "parent_set",
+ "GtkObject *old_parent"},
+
+ {"GtkWidget", "remove_accelerator",
+ "GtkAccelGroup *accel_group",
+ "guint accel_key",
+ "GdkModifierType accel_mods"},
+ {"GtkWidget", "debug_msg",
+ "gchar *message"},
+ {"GtkWindow", "move_resize",
+ "gint *x",
+ "gint *y",
+ "gint width",
+ "gint height"},
+ {"GtkWindow", "set_focus",
+ "GtkWidget *widget"},
+
+ {"GtkWidget", "selection_get",
+ "GtkSelectionData *data",
+ "guint info",
+ "guint time"},
+ {"GtkWidget", "selection_received",
+ "GtkSelectionData *data",
+ "guint time"},
+
+ {"GtkWidget", "drag_begin",
+ "GdkDragContext *drag_context"},
+ {"GtkWidget", "drag_end",
+ "GdkDragContext *drag_context"},
+ {"GtkWidget", "drag_data_delete",
+ "GdkDragContext *drag_context"},
+ {"GtkWidget", "drag_leave",
+ "GdkDragContext *drag_context",
+ "guint time"},
+ {"GtkWidget", "drag_motion",
+ "GdkDragContext *drag_context",
+ "gint x",
+ "gint y",
+ "guint time"},
+ {"GtkWidget", "drag_drop",
+ "GdkDragContext *drag_context",
+ "gint x",
+ "gint y",
+ "guint time"},
+ {"GtkWidget", "drag_data_get",
+ "GdkDragContext *drag_context",
+ "GtkSelectionData *data",
+ "guint info",
+ "guint time"},
+ {"GtkWidget", "drag_data_received",
+ "GdkDragContext *drag_context",
+ "gint x",
+ "gint y",
+ "GtkSelectionData *data",
+ "guint info",
+ "guint time"},
+
+ {NULL}
+ };
+
+ gint i;
+
+ for (i = 0; GbArgTable[i][0]; i++)
+ {
+ if (!strcmp (type, GbArgTable[i][0])
+ && !strcmp (signal_name, GbArgTable[i][1]))
+ return &GbArgTable[i][2];
+ }
+ return NULL;
+}
+
+
+static void
+output_widget_hierarchy ()
+{
+ FILE *fp;
+
+ fp = fopen (hierarchy_filename, "w");
+ if (fp == NULL)
+ {
+ g_warning ("Couldn't open output file: %s", hierarchy_filename);
+ return;
+ }
+ output_hierarchy (fp, GTK_TYPE_OBJECT, 0);
+ fclose (fp);
+}
+
+
+static void
+output_hierarchy (FILE *fp,
+ GtkType type,
+ gint level)
+{
+ GList *list;
+ guint i;
+
+ if (!type)
+ return;
+
+ for (i = 0; i < level; i++)
+ fprintf (fp, " ");
+ fprintf (fp, gtk_type_name (type));
+ fprintf (fp, "\n");
+
+ list = gtk_type_children_types (type);
+
+ while (list)
+ {
+ GtkType child = (GtkType) list->data;
+ output_hierarchy (fp, child, level + 1);
+ list = list->next;
+ }
+}
+EOT
+
+close OUTPUT;
+
+# Compile and run our file
+
+$CC = $ENV{CC} ? $ENV{CC} : "gcc";
+$CFLAGS = $ENV{CFLAGS} ? $ENV{CFLAGS} : "";
+$LDFLAGS = $ENV{LDFLAGS} ? $ENV{LDFLAGS} : "";
+
+$command = "$CC $CFLAGS -o $MODULE-scan $MODULE-scan.c $LDFLAGS";
+print "$command\n";
+
+system($command) == 0 or die "Compilation of scanner failed\n";
+
+system("./$MODULE-scan") == 0 or die "Scan failed\n";
+
+unlink "./$MODULE-scan.c", "./$MODULE-scan",