This directory contains the gtkmm preprocessor used for wrapping 
gtk+ objects.

------------------------------------------------------------------------
Use of the gtkmm preprocessor
=============================

How it works
------------
Gtkmmproc is a 3 pass process.  
1. Parse .hg/.ccg files and generate meta m4 macros in a tmp file (e.g. gtkmmproc5466.g1)
2. run m4 to expand macro text (to get e.g. (e.g. gtkmmproc5466.g2)
3. snip file into pieces. (.h .private_h, .cc)

1.
The first pass is to escape anything which may cause problems 
with m4 processing of a file.  This pass is performed in perl.
It also implements meta macros which are macros in which 
a C++ declaration must be broken into an argument list.
Commands marked with <meta> are implmented at this
level.

TODO: <meta> ? Is this still true? murrayc

At this point there is a file (e.g. /tmp/gtkmmproc5466.g1)
which contains text and m4 code. This m4 code is our m4
macros which will be expanded in the next pass.

2.
The second pass does both expansion and rearrangement of 
code.  The entire file including both the .hg headers and the
.ccg source files are processed as one piece.  This is because
some macros expand into multiple sections.  Commands marked
with <m4> are implemented at this level.

3.
The third pass is to take the M4 output and snip it into
the actually header and implementation files for use.
There are no commands which communicate directly with this layer,
though any raw C++ code from the .hg/.ccg files will of course be
carried through to here.

All macros are in capitals and are proceed by an underscore.


Output files
-------------

gtkmmproc generates 3 output files.  One is the header for inclusion
in user code.  The other is the implementation including implementing
all the macro built functions.  The last is a private header.  The
private header contains all the functions which are necessary to
derive a C object in the gtk+ object system from this widget.  
The private header is not for user consumption.  


Sectioning
-----------

Much of the magic of gtkmmproc happens at the m4 level.  
This includes sectioning.  Sectioning is method in which a macro
can create pieces of text after or before the expansion of the
macro.  Sectioning is done with the m4 divert command.
The macros _SECTION(), _PUSH() and _POP() are used to 
control what section is being writen. 

It is important to understand how the sections of a class 
are assembled.

Example:

  something.hg:
    #include <foo.h>
    
    namespace Gtk {
  
    class SomeThing 
      {
        WRAP_CLASS(...)
        public:
        // my methods
        void do();
      };
    }

  something.cmm:
    void Gtk::SomeThing::do() {}

This will be broken up into the following sections
<<>> represents a include section. * marks macro expansions.
(Names don't match current code look at m4 file to see what current
name is.)

  something.h:
*   #ifndef SOMETHING_H
*   #define SOMETHING_H
    #include <foo.h>
    <<FORWARD>>
    namespace Gtk {
    class SomeThing {
      {
*      public:
*        typedef ...
*        ....
       public:
       // my methods
       void do();

       <<IMPL>>
      };

    }
    #endif
 
  something.cc:
    void Gtk::SomeThing::do() {}

*   void gtkmm_something_init_type(
*     ....
    <<METHOD>>
    <<SIGNAL>>
    <<MEMBER>>

  something_p.h:
*   class SomeThing_Class {
    <<PRIVATE>>
*   };


If you, for example, need to place something in PRIVATE for this
class, you would do

  class SomeThing {
     ....
  _SECTION(PRIVATE)
    my stuff
  _SECTION(CLASS)
  }


In order to improve clarity the m4 template is expanded into
multiple files, one for each type of macro processed.
 
Command Summary
==================
 #m4            (meta)  one line m4 escape
 #m4begin       (meta)  multi line m4 escape
 #m4end         (meta)  end of multi line escape
 _CTOR_CAST     (class) implement the cast constructor automatically
 _CTOR_DEFAULT  (class) implement a constructor taking no arguments
 _DTOR          (class) implement the dtor automatically
 _MEMBER        (class) implement a member 
 _POP           (base)  save current section and switch to another
 _PINCLUDE      (base)  specify the parents private header name
 _PUSH          (base)  restore current section
 _SECTION       (base)  change sections
 _WRAP          (meta)  wrap various C types 
 _DEFS          (meta)  load a defs file
 _IGNORE        (?)     tells gtkmmproc not to complain this function not wrapped
  

M4 macro escaping <meta>
-----------------
At times it is useful to be able to issue commands directly to
m4 preprocessor underneith gtkmmproc.  However, for safety 
the single quote and backtick were hiden.  Thus you must
enter a special environment to be about to issue m4 commands
without interpretation.

single line m4 statements are any line proceed with a #m4.
  #m4 don't eat my `backticks'

Multiline m4 statements can be done with #m4begin/#m4end

  #m4begin
  define(`convert', `dnl
  gtkmm_convert($1,$2->obj);
  ')
  #m4end

_DEFS (meta)
------------
Takes one argument which is the def file to read.


Debugging
---------
If you see m4 errors, you can set the GTKMMPROC_DEBUG environment variable like so:
# export GTKMMPROC_DEBUG=1
This will ensure that the intermediate m4 files are not deleted, so that you can examine them.


_WRAP_METHOD( C++ declaration, C function name )
------------------------------------------------

e.g. From entry.hg:
_WRAP_METHOD(void set_text(const string &text),gtk_entry_set_text)

The C function (e.g. gtk_entry_set_text) is described in gtk/src/gtk.defs,
which is generated automatically by the h2defs.py script from pygtk.


_WRAP_SIGNAL( C++ handler declaration, "signal name" )
------------------------------------------------------

e.g. From button.hg:
_WRAP_SIGNAL(void clicked(),"clicked")

Signals are function pointers in the GTK Class struct, with a
corresponding enum value. and a gtk_signal_new.

from gtkbutton.h:

struct _GtkButtonClass
{
 GtkBinClass parent_class;

 void (* pressed) (GtkButton *button);
 void (* released) (GtkButton *button);
 void (* clicked) (GtkButton *button);
 ...
};

from gtkbutton.c:

enum {
 PRESSED,
 RELEASED,
 CLICKED,
 ENTER,
 LEAVE,
 ACTIVATE,
 LAST_SIGNAL
};

and

button_signals[CLICKED] =
 gtk_signal_new ("clicked",
 GTK_RUN_FIRST | GTK_RUN_ACTION,
 GTK_CLASS_TYPE (object_class),
 GTK_SIGNAL_OFFSET (GtkButtonClass, clicked),
 gtk_marshal_VOID__VOID,
 GTK_TYPE_NONE, 0);


The signals are described in gtk_signals.defs using the define-signal
command. This file was created by the tools/generate_defs utility.
You might need to modify the defs slightly.

You might find a similarly named method. Just wrap it separately as a
method, and don't worry about the names clashing.
e.g _WRAP_METHOD(void clicked(), gtk_button_clicked)


_MEMBER_GET(gtkmm name, gtk+ name, C++ type, C type)
----------------------------------------------------

e.g. from window.hg:
_MEMBER_GET(window_type, type, GtkWindowType, GtkWindowType)

In GTK+, you're sometimes supposed to read from an object data field directly.
This macro creates a get_*() method for use with C++.


_MEMBER_SET(gtkmm name, gtk+ name, C++ type, C type)
----------------------------------------------------

e.g. from buttonbox.hg:
_MEMBER_SET(child_min_width, child_min_width, int, gint)

In GTK+, you're sometimes supposed to write to an object data field directly.
This macro creates a set_*() method for use with C++.


_MEMBER_GET_PTR(gtkmm name, gtk+ name, C++ pointer type, C pointer type)
------------------------------------------------------------------------

e.g. from progress.hg:
_MEMBER_GET_PTR(adjustment, adjustment, Gtk::Adjustment*, GtkAdjustment*)

Similar to _MEMBER_GET(), but this macro create two access methods:
A non-const method that returns a pointer to a writable object, and
a const method returning a pointer to a read-only object.


_MEMBER_GET_GOBJECT(gtkmm name, gtk+ name, C++ type, C pointer type)
--------------------------------------------------------------------

e.g. from window.hg:
_MEMBER_GET_GOBJECT(frame, frame, Gdk::Window, GdkWindow*)

Similar to _MEMBER_GET_PTR(), this macro creates two access methods.
The difference is that the return types will actually be
Glib::RefPtr<C++ type> and Glib::RefPtr<const C++ type>.

Also, the methods call object->reference() before
returning it to the caller.


_WRAP_PROPERTY("property name", C++ type)
-----------------------------------------

e.g. From Widget.hg:
_WRAP_PROPERTY("name", Glib::ustring)

The properties are described in gtk_signals.defs using the
define-property command. This file was created by the
tools/generate_defs utility. You might need to modify the defs
slightly.

Properties have enum values in the .c file. e.g from gtkwidget.c:

enum {
  PROP_0,
  PROP_NAME,
  PROP_PARENT,
...

These enums are used in a call to g_object_class_install_property().
e.g. from gtkwidget.c:

  g_object_class_install_property (gobject_class,
				   PROP_NAME,
				   g_param_spec_string ("name",
 							_("Widget name"),
							_("The name of the widget"),
							NULL,
							G_PARAM_READWRITE));

This sometimes shows the type of the property, but sometimes you
need to look for the use of the property enum to see what type
of values are being used with it. For instance, from gtkwidget.c:

static void
gtk_widget_get_property (GObject         *object,
			 guint            prop_id,
			 GValue          *value,
			 GParamSpec      *pspec)
{
  GtkWidget *widget;

  widget = GTK_WIDGET (object);

  switch (prop_id)
    {
      gint *eventp;
      GdkExtensionMode *modep;

    case PROP_NAME:
      if (widget->name)
...

By looking at GtkWidget::name you can see the type.

The defs file also shows the types of the properties, but
when the type is an enum, flag, or object, it doesn't show
the exact type.


_WRAP_VFUNC( C++ declaration, vfunc C name )
--------------------------------------------

e.g. From checkbutton.hg:
_WRAP_VFUNC(void draw_indicator(GdkRectangle* area),"draw_indicator")

These are quite unusual, but you'll probably find one or two. They
are function pointers in the GTK Class struct, which have no
gtk_signal_new().

For instance, from gtkcheckbutton.h:

struct _GtkCheckButtonClass
{
 GtkToggleButtonClass parent_class;

 void (* draw_indicator) (GtkCheckButton *check_button,
 GdkRectangle *area);
};

And from gtkcheckbutton.c:

class->draw_indicator = gtk_real_check_button_draw_indicator;

The virtual functions are described in gtk_vfuncs.defs using the
define-vfunc command. This file was created manually so you will
need to add a section to it for each new virtual function that you find.


