		A small Introduction to the `gtkgen' Command
		-==========================================-

      (by Elmar Ludwig <Elmar.Ludwig@uos.de>, last update: 2000-12-25)

As you may have noticed (or maybe not), most of the source files of the
GToolKit library are automatically generated from the GTK+ include files.
The program that does this is called `gtkgen' and resides in the GToolKit
directory in this archive. There is also small helper script (`mkclasses')
that can be used to build class table input files for gtkgen. Both scripts
have been written in Perl for maximum readability... ;-)

Fine. But why should you bother?

Well, there are several other useful add-on libraries available for GTK+
(like gtkhtml or gtk-extra) that may contain some classes you want to use
in your own Objective-C programs. Of course, you can always work with the
plain C interface of these libraries (since Objective-C is an extension of
ANSI-C), but there is also another approach: You can take the scripts that
are used to generate the GToolKit source code and apply them to other
libraries.

I will try to explain here in short the basic procedure necessary.

Basically, the process of creating a set of Objective-C wrapper classes
for a collection of GTK+ classes (I use this term here to refer to a class
written in C using the GTK/GLIB object system) is a two step process:

  - Build a class table file containing some vital information about the
    classes that should be wrapped, plus all the classes that may appear
    (as parameter or return types) in these classes' header files. This
    information will then be used by gtkgen during the second step (see
    below). You can prevent any class from being wrapped just be omitting
    it from the class table file.

  - Create the actual Objective-C interface (`.h') and implementation
    (`.m') files from the corresponding C include files of the classes
    you need to wrap. It is also possible to add additional methods or
    instance variables to the created files during this step.

You can see this process in action by looking at how the GToolKit source
code is generated. First, I run `make genclean' to delete all generated
files in the GToolKit source directory:

  $ make genclean
  rm -f GToolKit.h `sed 's/^[^;]*;\([^;]*\);.*/\1.h/' classes.in`
  rm -f GToolKit.m `sed 's/^[^;]*;\([^;]*\);.*/\1.m/' classes.in`
  rm -f -r ../html GTKMain.h GTKMain.m classes.in

Although this has nothing to do with gtkgen, I use this to make sure that
all files will be rebuilt. (Note that this will also delete the generated
HTML documentation files in the html directory, which you cannot recreate
at the moment, because the program which will do that is not included in
this archive.)

  $ make gen
  ./mkclasses --add GtkAccelGroup --add GtkMenuFactory \
              --exclude GtkType --path gtk \
              /usr/local/include/gtk/*.h | sort >classes.in
  ./gtkgen --output GToolKit.m --package GToolKit --strict \
           /usr/local/include/gtk/*.h
  skipping gtk.h...
  skipping gtkarg.h...
  skipping gtkbindings.h...
  skipping gtkcompat.h...
  skipping gtkdebug.h...
  skipping gtkdnd.h...
  skipping gtkenums.h...
  skipping gtkfeatures.h...
  skipping gtkgc.h...
  skipping gtkmarshal.h...
  skipping gtkprivate.h...
  skipping gtkrc.h...
  skipping gtkselection.h...
  skipping gtksignal.h...
  skipping gtkthemes.h...
  skipping gtktypebuiltins.h...
  skipping gtktypeutils.h...

As you can see above, I use the `mkclasses' script to extract a list of
all GTK+ classes from the complete set of GTK+ include files, which is
then sorted and written to the file `classes.in' (though the list does
not have to be sorted any more, early versions of gtkgen required this).

You can perform a (very) limited degree of fine-tuning using the `--add'
and `--exclude' options of mkclasses. `--add' will include an additional
class in the class table, but it will have to *guess* the proper output
from the class name (which is ok here), while `--exclude' will omit the
given class from the class table. The option `--path' specifies the name
(or path) of the C include directory of all file arguments relative to
the standard include path of the C compiler. In this case, it is `gtk'.

The output of the first command (mkclasses) typically looks like this:

  [...]
  GtkBin;GTKBin;bin;gtk_bin;GtkContainer;gtk/gtkbin.h
  GtkBox;GTKBox;box;gtk_box;GtkContainer;gtk/gtkbox.h
  GtkButton;GTKButton;button;gtk_button;GtkBin;gtk/gtkbutton.h
  GtkButtonBox;GTKButtonBox;buttonBox;gtk_button_box;GtkBox;gtk/gtkbbox.h
  [...]

Each output line describes a list of properties for a single class (the
info fields are separated by `;'), where the individual fields have the
following meaning:

  - the GTK+ class name
  - the corresponding Objective-C class name
  - the method name prefix of the Objective-C allocator method (prefix of
    the class method that will return a new autoreleased instance of this
    class, this is typically named after the class name)
  - the common C function name prefix of all GTK+ functions in this class
  - the GTK+ class name of the super class (leave empty if there is none)
  - the name of the C include file of this class

After that, gtkgen is called to scan the C include files for method names
and create the Objective-C include and source code files. By default, it
will create two files for each class: `classname.h' and `classname.m'.
Alternatively, you can set a single output file (or `-' for stdout) for
all class implementations (which can considerably speed up compilation
times). In this case, only one file per class (`classname.h') is created,
in addition to the given output file. If you want to add custom methods
to the generated files, read the comments at the beginning of the gtkgen
script (you need to supply a file `classname.in' for this).

Optionally (with `--package'), gtkgen can also create a package include
file for a collection of Objective-C classes (one file that includes all
the others, similar to Foundation/Foundation.h or GToolKit/GToolKit.h).
The last option, `--strict', is used to enable stricter source formatting
rules for the C include files. Currently, the only real difference is the
handling of the type `char *' in a function's argument list. In strict
mode, gtkgen will assume that such a function will modify its argument
(because there is no `const' in front of `char *').

That's it.
Finally, we should look at a small practical example:

Let's assume you wish to create an Objective-C wrapper class for the
GtkHTML class from the gtkhtml library (which can be found on the GNOME
FTP server).

In this simple example, I just need to do the following:

  $ cd gtkhtml-0.5/src
  $ ls gtk*
  gtkhtml-embedded.c    gtkhtml-properties.h  gtkhtmldebug.c
  gtkhtml-embedded.h    gtkhtml-stream.c      gtkhtmldebug.h
  gtkhtml-keybinding.h  gtkhtml-stream.h      gtkhtmlfontstyle.c
  gtkhtml-private.h     gtkhtml.c             gtkhtmlfontstyle.h
  gtkhtml-properties.c  gtkhtml.h
  $ mkclasses --path gtkhtml gtkhtml.h
  GtkHTML;GTKHTML;html;gtk_html;GtkLayout;gtkhtml/gtkhtml.h
  $ cp ~/Work/gtoolkit-0.9.4/GToolKit/classes.in .
  $ mkclasses --path gtkhtml gtkhtml.h >>classes.in

Although I am only interested in the GtkHTML class here, it is important
that the class input file (`classes.in') contains a complete list of *all*
the classes that may appear in the header files you want to process. As
including more classes does not really hurt, I would strongly recommend to
always start with the `classes.in' file provided with the GToolKit library
and then add the additional classes you want to wrap.

Of course, you can also write these additional class table entries by hand
if the output of mkclasses is not correct (which may happen if a class does
not exactly follow the usual GTK+ naming conventions).

Now, I can proceed by creating the actual Objective-C source code files
for the GTKHTML class by invoking the `gtkgen' command:

  $ gtkgen gtkhtml.h
  skipping gtkhtml.h...

That surely doesn't look right. What went wrong here?
(gtkgen will warn you if it did not create a class for an input file.)

Well, I told mkclasses (in step one above) that the name of the GtkHTML
include file is `gtkhtml/gtkhtml.h'. This is true, but only *after* the
library has been installed (which I did not want to do for this short
demonstration). So I have to either:

  {install the gtkhtml library}
  $ gtkgen /usr/local/include/gtkhtml/gtkhtml.h

or use a simple trick to fool gtkgen:

  $ ln -s . gtkhtml
  $ gtkgen gtkhtml/gtkhtml.h

Now I have successfully created the wrapper class:

  $ ls -lt | head -6
  total 1486
  -rw-r--r--   1 elmar    users        3408 Dec 25 20:48 GTKHTML.m
  -rw-r--r--   1 elmar    users        2035 Dec 25 20:48 GTKHTML.h
  lrwxrwxrwx   1 elmar    users           1 Dec 25 20:48 gtkhtml -> .
  -rw-r--r--   1 elmar    users        7089 Dec 25 20:43 classes.in
  drwxrwxr-x   2 elmar    users        1024 Jul 11 01:29 tests

A final note:
In order to properly support file systems that do not use case sensitive
filenames (like FAT or NTFS), you cannot use the same include directory
name for the C and Objective-C versions of the same class (since the names
`gtkhtml/gtkhtml.h' and `gtkhtml/GTKHTML.h' would refer to the same file).

Therefore, the Objective-C include directory is distinguished by adding
the suffix `_objc' at the end of the directory name, as you can see in the
generated file GTKHTML.m:

  [...]
  #include <gtkhtml_objc/GTKHTML.h>
  #include <GToolKit/GTKWidget.h>

  @implementation GTKHTML
  [...]
