diff options
-rw-r--r-- | AUTHORS | 3 | ||||
-rw-r--r-- | ChangeLog | 0 | ||||
-rw-r--r-- | Makefile.am | 16 | ||||
-rw-r--r-- | NEWS | 0 | ||||
-rw-r--r-- | README | 137 | ||||
-rw-r--r-- | acconfig.h | 25 | ||||
-rwxr-xr-x | autogen.sh | 66 | ||||
-rw-r--r-- | configure.in | 52 | ||||
-rw-r--r-- | db2man/README | 14 | ||||
-rwxr-xr-x | db2man/docbook-to-man | 178 | ||||
-rw-r--r-- | db2man/docbook-to-man.ts | 2019 | ||||
-rw-r--r-- | doc/README | 26 | ||||
-rw-r--r-- | doc/authors.txt | 174 | ||||
-rw-r--r-- | doc/gnome.txt | 79 | ||||
-rw-r--r-- | doc/gtk_button.txt | 235 | ||||
-rw-r--r-- | doc/manpage | 170 | ||||
-rw-r--r-- | doc/manpage.man | 140 | ||||
-rw-r--r-- | doc/notes.txt | 180 | ||||
-rw-r--r-- | gtk-doc.cat | 4 | ||||
-rw-r--r-- | gtk-doc.dsl.in | 206 | ||||
-rw-r--r-- | gtk-doc.dtd | 10 | ||||
-rwxr-xr-x | gtkdoc-mkdb | 1159 | ||||
-rw-r--r-- | gtkdoc-mkhtml.in | 19 | ||||
-rw-r--r-- | gtkdoc-mkman.in | 27 | ||||
-rwxr-xr-x | gtkdoc-mktmpl | 466 | ||||
-rwxr-xr-x | gtkdoc-scan | 381 | ||||
-rwxr-xr-x | gtkdoc-scanobj | 680 |
27 files changed, 6466 insertions, 0 deletions
@@ -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 + @@ -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 < or > 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 “Algorithm” 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>• +</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>• +</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>• +</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> :</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> :</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 <$HEADER_FILE> + +${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. '<' -> '<' +sub CreateValidSGML { + local ($text) = $_[0]; + $text =~ s/&/&/g; # Do this first, or the others get messed up. + $text =~ s/</</g; + $text =~ s/>/>/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 = ¶m_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", |