GtkAda User’s Guide

Next:   [Contents]

1 Introduction: What is GtkAda ?

GtkAda is a high-level portable graphical toolkit, based on the gtk+ toolkit, one of the official GNU toolkits. It makes it easy to create portable user interfaces for multiple platforms, including most platforms that have a X11 server and Win32 platforms.

Although it is based on a C library, GtkAda uses some advanced Ada features such as tagged types, generic packages, access to subprograms, and exceptions to make it easier to use and design interfaces. For efficiency reasons, it does not use controlled types, but takes care of all the memory management for you in other ways.

As a result, this library provides a secure, easy to use and extensible toolkit.

Compared to the C library, GtkAda provides type safety (especially in the callbacks area), and object-oriented programming. As opposed to common knowledge, it requires less type casting than with in C. Its efficiency is about the same as the C library through the use of inline subprograms.

GtkAda comes with a complete integration to the graphical interface builder Glad. This makes it even easier to develop interfaces, since you just have to click to create a description of the window and all the dialogs. Ada code can simply import that description to bring the windows to life.

Under some platforms, GtkAda also provides a bridge to use OpenGL, with which you can create graphical applications that display 3D graphics, and display them in a GtkAda window, as with any other 2D graphics. This manual does not document OpenGL at all, see any book on OpenGL, or the specification that came with your OpenGL library, for more information.

The following Internet sites will always contain the latest public packages for GtkAda, gtk+, Glade and Cairo

http://libre.adacore.com/libre/tools/GtkAda/

http://www.gtk.org/

http://glade.gnome.org/

http://www.cairographics.org/

The scheme used for GtkAda’s version numbers is the following: the major and minor version number is the same as for the underlying gtk+ library (e.g 2.18). The micro version number depends on GtkAda’s release number.

This toolkit was tested on the following systems:

with the latest version of the GNAT compiler, developed and supported by Ada Core Technologies (see http://www.adacore.com).

This version of GtkAda is known to be compatible with gtk+ 2.16.x and 2.18.x. This release may or may not be compatible with older versions of gtk+.

This version of GtkAda is compatible with Glade version 3.7.3.

This document does not describe all the widgets available in GtkAda, nor does it try to explain all the subprograms. The GtkAda Reference Manual provides this documentation instead, as well as the GtkAda sources spec files themselves, whose extension is .ads.

No complete example is provided in this documentation. Instead, please refer to the examples that you can find in the testgtk/ and examples/ directory in the GtkAda distribution, since these are more up-to-date (and more extensive). They are heavily commented, and are likely to contain a lot of information that you might find interesting.

If you are interested in getting support for GtkAda–including priority bug fixes, early releases, help in using the toolkit, help in designing your interface, and on site consulting–please contact AdaCore (mailto:sales@adacore.com).


Next: , Previous:   [Contents]

2 Getting started with GtkAda

This chapter describes how to start a new GtkAda application. It explains the basic features of the toolkit, and shows how to compile and run your application.

It also gives a brief overview of the extensive widget hierarchy available in GtkAda.


Next: , Up: Getting started with GtkAda   [Contents]

2.1 How to build and install GtkAda

This section explains how to build and install GtkAda on your machine.

On Windows systems, we provide an automatic installer that installs GtkAda along with dependent components like gtk+ libraries and Glade. If you are a Windows user, you can skip the rest of this section which will address installation on Unix systems.

On Unix systems, you first need to install the glib and gtk+ libraries. Download the compatible packages from the gtk+ web site (http://www.gtk.org), compile and install it. Alternatively, if your operating system vendor provides glib and gtk+ development packages, you can install the libraries they provide.

Change your PATH environment variable so that the script pkg-config, which indicates where gtk+ was installed and what libraries it needs is automatically found by GtkAda. You will no longer need this script once GtkAda is installed, unless you develop part of your application in C.

OpenGL support will not be activated in GtkAda unless you already have the OpenGL libraries on your systems. You can for instance look at Mesa, which is free implementation.

Optionally, you can also install the Glade interface builder. Get the compatible package from the Glade web site, compile and install it.

You can finally download the latest version of GtkAda from the web site. Untar and uncompress the package, then simply do the following steps:

$ ./configure
$ make
$ make tests     (this step is optional)
$ make install

As usual with the configure script, you can specify where you want to install the GtkAda libraries by using the --prefix switch.

You can specify the switch --disable-shared to prevent building shared libraries, even if your system supports them (by default, both shared and static libraries are installed). By default, your application will be linked statically with the GtkAda libraries. You can override this default by specifying --enable-shared as a switch to configure, although you can override it later through the LIBRARY_TYPE scenario variable.

If you have some OpenGL libraries installed on your system, you can make sure that configure finds them by specifying the --with-GL-prefix switch on the command line. configure should be able to automatically detect the libraries however.

You must then make sure that the system will be able to find the dynamic libraries at run time if your application uses them. Typically, you would do one of the following:

In addition, if you are using precompiled Gtk+ binary packages, you will also need to set the FONTCONFIG_FILE environment variable to point to the prefix/etc/fonts/fonts.conf file of your binary installation.

For example, assuming you have installed Gtk+ under /opt/gtk and using bash:

$ export FONTCONFIG_FILE=/opt/gtk/etc/fonts/fonts.conf

If your application is using printing, on UNIX and Linux you will need to point your environment variable GTK_EXE_PREFIX to the root directory of your Gtk+ installation:

$ export GTK_EXE_PREFIX=/opt/gtk/

Next: , Previous: , Up: Getting started with GtkAda   [Contents]

2.2 How to distribute a GtkAda application

Since GtkAda depends on Gtk+, you usually need to distribute some Gtk+ libraries along with your application.

Under some OSes such as Linux, Gtk+ comes preinstalled, so in this case, a simple solution is to rely on the preinstalled Gtk+ libraries. See below for more information on the gtkada library itself.

Under other unix systems, GtkAda usually comes with a precompiled set of Gtk+ libraries that have been specifically designed to be easily redistributed.

In order to use the precompiled Gtk+ binaries that we distribute with GtkAda, you need to distribute all the Gtk+ .so libraries along with your application, and use the LD_LIBRARY_PATH environment variable to point to these libraries.

The list of libraries needed is <gtkada-prefix>/lib/lib*.so.? along with your executable, and set LD_LIBRARY_PATH.

You may also need the libgtkada-xxx.so file. This dependency is optional since gtkada supports both static and dynamic linking, so by e.g. using gtkada-config --static or by using gtkada_static.gpr, you will end up linking with libgtkada.a.

Under Windows, you need to distribute the following files and directories along with your application, and respect the original directory set up:


Next: , Previous: , Up: Getting started with GtkAda   [Contents]

2.3 Organization of the GtkAda package

In addition to the full sources, the GtkAda package contains a lot of heavily commented examples. If you haven’t been through those examples, we really recommend that you look at them and try to understand them, since they contain some examples of code that you might find interesting for your own application.


Next: , Previous: , Up: Getting started with GtkAda   [Contents]

2.4 How to compile an application with GtkAda

This section explains how you can compile your own applications.

There are several ways to use GtkAda in your applications

2.4.1 Using project files

A set of project files is installed along with GtkAda. If you have installed GtkAda in the same location as GNAT itself, nothing else needs to be done.

Otherwise, you need to make the directory that contains these project files visible to the compiler. This is done by adding the directory to the ADA_PROJECT_PATH environment variable. Assuming you have installed the library in prefix, the directory you need to add is prefix/lib/gnat.

On Unix, this is done with

csh:
   setenv ADA_PROJECT_PATH $prefix/lib/gnat:$ADA_PROJECT_PATH
sh:
   ADA_PROJECT_PATH=$prefix/lib/gnat:$ADA_PROJECT_PATH
   export ADA_PROJECT_PATH

To build your own application, you should then setup a project file (see the GNAT documentation for more details on project files), which simply contains the statement

with "gtkada";

This will automatically set the right compiler and linker options, so that your application is linked with GtkAda.

By default, the linker will use GtkAda’s shared library, if it was built. If you would prefer to link with the static library, you can set the environment variable LIBRARY_TYPE=static export LIBRARY_TYPE before launching the compiler or linker, which will force it to use the static library instead.

2.4.2 Using the command line

The procedure is system-dependent, and thus is divided into two subsections.

2.4.2.1 Unix systems

On Unix systems, a script called gtkada-config is automatically created when you build GtkAda. This script is copied in a subdirectory bin/ in the installation directory.

The easiest and recommended way to build a GtkAda application is to use the gnatmake program distributed with GNAT, that takes care of all the dependencies for you. Use the gtkada-config to specify where GtkAda and gtk+ libraries have been installed.

> gnatmake <main-file> `gtkada-config`

Note the use of back-ticks around gtkada-config, which force the shell to evaluate the script and put the output on the command line.

However, on complex systems, gnatmake might not be enough. Users frequently like to create Makefiles. The script gtkada-config remains useful in that case, since you can call it from your Makefile (same syntax as above with the back-ticks) to create variables like FLAGS and LIBS. See the switches of gtkada-config below for more information.

The script gtkada-config understands the following command line switches (chosen to be compatible with the ones set by gtk-config):

2.4.2.2 Windows systems

Things are somewhat easier on Windows systems. You don’t have access to the gtkada-config script. On the other hand you also don’t have to specify which libraries to use or where to find them.

The only thing you should specify on the gnatmake command line is where the GtkAda spec files are found, as in:

> gnatmake <main-file> -Ic:\gtkada\include\gtkada

if GtkAda was installed under c:\gtkada.


Next: , Previous: , Up: Getting started with GtkAda   [Contents]

2.5 Architecture of the toolkit

The gtk+ toolkit has been designed from the beginning to be portable. It is made of two libraries: gtk and gdk. In addition, GtkAda provides binding to three supporting libraries: pango, cairo and glib.

Glib is a non-graphical library that includes support for lists, h-tables, threads, and so on. It is a highly optimized, platform-independent library. Since most of its contents are already available in Ada (or in the GNAT.* hierarchy in the GNAT distribution), GtkAda does not include a complete binding to it. For the parts of Glib that we do depend on, we provide Glib.* packages in the GtkAda distribution.

Gdk is the platform-dependent part of gtk+, and so there are different implementations (for instance, for Win32 and X11 based systems) that implement a common API. Gdk provides basic graphical functionality to, for instance, draw lines, rectangles and pixmaps on the screen, as well as manipulate colors. The Gdk.* packages provide a full Ada interface to Gdk.

Pango is a modern font handling system. Bindings in GtkAda gives access to the API to manipulate font descriptions and text attributes.

Cairo is the low-level 2D drawing library used by Gdk to render widgets. Cairo provides a rich set of vector drawing features, supporting anti-aliasing, transparency, and 2D matrix transformations.The Cairo.* packages provide a complete Ada binding to Cairo.

Gtk is the top level library. It is platform independent, and does all its drawing through calls to Gdk and Cairo. This is where the high-level widgets are defined. It also includes support for callbacks. Its equivalent in the GtkAda libraries are the Gtk.* packages. It is made of a fully object-oriented hierarchy of widgets (see Widgets Hierarchy).

Since your application only calls GtkAda, it is fully portable, and can be recompiled as-is on other platforms.

+------------------------------- ----------+
|             Your Application             |
+------------------------------------------+
|                 GtkAda                   |
|              +-----------------+         |
|              |      GTK        |         |
|         +----+-----------------+----+    |
|         |           GDK             |    |
|    +----+------+         +----------+----+
|    |   Pango   |         |     Cairo     |
+----+-----------+----+----+---------------+
|        GLIB         |   X-Window / Win32  |
+---------------------+--------------------+

Although the packages have been evolving a lot since the first versions of GtkAda, the specs are stabilizing now. We will try as much as possible to provide backward compatibility whenever possible.

Since GtkAda is based on gtk+ we have tried to stay as close to it as possible while using high-level features of the Ada language. It is thus relatively easy to convert external examples from C to Ada.

We have tried to adopt a consistent naming scheme for Ada identifiers:

WARNING: all the generic packages allocate some memory for internal structures, and call internal functions. This memory is freed by gtk itself, by calling some Ada functions. Therefore the generic packages have to be instantiated at library level, not inside a subprogram, so that the functions are still defined when gtk needs to free the memory.

WARNING Before any other call to the GtkAda library is performed, Gtk.Main.Init must be invoked first. Most of the time, this procedure is invoked from the main procedure of the application, in which case no use of GtkAda can be done during the application elaboration.


Previous: , Up: Getting started with GtkAda   [Contents]

2.6 Widgets Hierarchy

All widgets in GtkAda are implemented as tagged types. They all have a common ancestor, called Gtk.Object.Gtk_Object. All visual objects have a common ancestor called Gtk.Widget.Gtk_Widget.

The following table describes the list of objects and their inheritance tree. As usual with tagged types, all the primitive subprograms defined for a type are also known for all of its children. This is a very powerful way to create new widgets, as will be explained in Creating new widgets in Ada.

Although gtk+ was written in C its design is object-oriented, and thus GtkAda has the same structure. The following rules have been applied to convert from C names to Ada names: a widget Gtk_XXX is defined in the Ada package Gtk.XXX, in the file gtk-xxx.ads. This follows the GNAT convention for file names. For instance, the Gtk_Text widget is defined in the package Gtk.Text, in the file gtk-text.ads.

Note also that most of the documentation for GtkAda is found in the spec files themselves.

It is important to be familiar with this hierarchy. It is then easier to know how to build and organize your windows. Most widgets are demonstrated in the testgtk/ directory in the GtkAda distribution.

hierarchy
            Hierarchy of widgets in GtkAda

Next: , Previous:   [Contents]

3 Hierarchical composition of a window

Interfaces in GtkAda are built in layers, as in Motif. For instance, a typical dialog is basically a Gtk_Window, that in turn contains a Gtk_Box, itself divided into two boxes and a Gtk_Separator, and so on.

boxes

Altough this may seem more complicated than setting absolute positions for children, this is the simplest way to automatically handle the resizing of windows. Each container that creates a layer knows how it should behave when it is resized, and how it should move its children. Thus almost everything is handled automatically, and you don’t have to do anything to support resizing.

If you really insist on moving the children to a specific position, look at the Gtk_Fixed widget and its demo in testgtk/. But you really should not use this container, since you will then have to do everything by hand.

All the containers are demonstrated in testgtk/, in the GtkAda distribution. This should help you understand all the parameters associated with the containers. It is very important to master these containers, since using the appropriate containers will make building interfaces a lot easier.

If you look at the widget hierarchy (see Widgets Hierarchy), you can see that a Gtk_Window inherits from Gtk_Bin, and thus can have only one child. In most cases, the child of a Gtk_Window will thus be a Gtk_Box, which can have any number of children.

Some widgets in GtkAda itself are built using this strategy, from the very basic Gtk_Button to the more advanced Gtk_File_Selection.

For example, by default a Gtk_Button contains a Gtk_Label, which displays the text of the button (like “OK” or “Cancel”).

However, it is easy to put a pixmap in a button instead. When you create the button, do not specify any label. Thus, no child will be added, and you can give it your own. See testgtk/create_pixmap.adb for an example on how to do that.


Next: , Previous:   [Contents]

4 Signal handling

In GtkAda, the interaction between the interface and the core application is done via signals. Most user actions on the graphical application trigger some signals to be ‘emitted’.

A signal is a message that an object wants to broadcast. It is identified by its name, and each one is associated with certain events which happen during the widget’s lifetime. For instance, when the user clicks on a Gtk_Button, a “clicked” signal is emitted by that button. More examples of signals can be found in the GtkAda reference manual.

It is possible to cause the application to react to such events by ‘connecting’ to a signal a special procedure called a ‘handler’ or ‘callback’. This handler will be called every time that signal is emitted, giving the application a chance to do any processing it needs. More than one handler can be connected to the same signal on the same object; the handlers are invoked in the order they were connected.


Next: , Up: Signal handling   [Contents]

4.1 Predefined signals

Widgets, depending on their type, may define zero or more different signals. The signals defined for the parent widget are also automatically inherited; thus every widget answers many signals.

The easiest way to find out which signals can be emitted by a widget is to look at the GtkAda reference manual. Every widget will be documented there. The GtkAda RM explains when particular signals are emitted, and the general form that their handlers should have (although you can always add a User_Data if you wish, see below).

You can also look directly at the C header files distributed with the gtk+ library. Each widget is described in its own C file and has two C structures associated with it. One of them is the “class” structure, which contains a series of pointers to functions. Each of these functions has the same name as the signal name.

For instance, consider the following extract from gtkbutton.h:

struct _GtkButtonClass
{
  GtkBinClass        parent_class;

  void (* pressed)  (GtkButton *button);
  void (* released) (GtkButton *button);
  void (* clicked)  (GtkButton *button);
  void (* enter)    (GtkButton *button);
  void (* leave)    (GtkButton *button);
};

This means that the Gtk_Button widget redefines five new signals called pressed, released, and so on, respectively.

The profile of the handler can also be deduced from those pointers: The handler has the same arguments, plus an optional User_Data parameter that can be used to pass any kind of data to the handler. When the User_Data parameter is used, the value of this data is specified when connecting the handler to the signal. It is then given back to the handler when the signal is raised.

Therefore, the profile of a handler should look like:

procedure Pressed_Handler
  (Button    : access Gtk_Button_Record'Class;
   User_Data : ...);

The callback does not need to use all the arguments. It is legal to use a procedure that "drops" some of the last arguments. There is one special case, however: if, at connection time, you decided to use User_Data, your callback must handle it. This is checked by the compiler.

Any number of arguments can be dropped as long as those arguments are the last ones in the list and you keep the first one. For instance, the signal "button_press_event" normally can be connected to a handler with any of the following profiles:

--  with a user_data argument
procedure Handler
  (Widget    : access Gtk_Widget_Record'Class;
   Event     : Gdk.Event.Gdk_Event;
   User_Data : ...);
procedure Handler
  (Widget    : access Gtk_Widget_Record'Class;
   User_Data : ...);

--  without a user_data argument
procedure Handler
  (Widget : access Gtk_Widget_Record'Class;
   Event  : Gdk.Event.Gdk_Event);
procedure Handler (Widget : access Gtk_Widget_Record'Class);

Beware that adding new arguments is not possible, since no value would be provided for them. When connecting a handler, GtkAda will not always verify that your handler does not have more arguments than expected, so caution is recommended (it only does so if you use the Gtk.Marshallers package, see below).


Next: , Previous: , Up: Signal handling   [Contents]

4.2 Connecting signals

All signal handling work is performed using services provided by the Gtk.Handlers package. This package is self-documented, so please read the documentation for this package either in the GtkAda Reference Manual or in the specs themselves. The rest of this section assumes that you have this documentation handy.

A short, annotated example of connecting signals follows; a complete example can be found in create_file_selection.adb (inside the testgtk/ directory). In our example, an application opens a file selector to allow the user to select a file. GtkAda provides a high-level widget called Gtk_File_Selection which can be used in this case:

declare
   Window : Gtk_File_Selection;
begin
   Gtk.File_Selection.Gtk_New (Window, Title => "Select a file");
end;

When the “OK” button is pressed, the application needs to retrieve the selected file and then close the dialog. The only information that the handler for the button press needs is which widget to operate upon. This can be achieved by the following handler:

procedure OK (Files : access Gtk_File_Selection_Record'Class) is
begin
   Ada.Text_IO.Put_Line ("Selected " & Get_Filename (Files));
   --  Prints the name of the selected file.
   Destroy (Files);
   --  Destroys the file selector dialog
end Ok;

We now need to connect the object we created in the first part with the new callback we just defined. Gtk.Handlers defines four types of generic packages, depending on the arguments one expects in the callback and whether the callback returns a value or not. Note that you can not use an arbitrary list of arguments; this depends on the signal, as explained in the previous section.

In our example, since the callback does not return any value and does not handle any User_Data (that is, we don’t pass it extra data, which will be specified at connection time), the appropriate package to use is Gtk.Handlers.Callback. We thus instantiate that package.

Remember that generic package instantiations in GtkAda must be present in memory at all times, since they take care of freeing allocated memory when finished. GtkAda generic package instantiations must therefore always be performed at the library level, and not inside any inner block.

package Files_Cb is new
  Handlers.Callback (Gtk_File_Selection_Record);

The Files_Cb package now provides a set of Connect subprograms that can be used to establish a tie between a widget and a handler. It also provides a set of other subprograms which you can use to emit the signals manually, although most of the time, the signals are simply emitted internally by GtkAda. We will not discuss the Emit_By_Name subprograms here.

The general form of handler, as used in Gtk.Handlers, expects some handlers that take two or three arguments: the widget on which the signal was applied, an array of all the extra arguments sent internally by GtkAda, and possibly some user data given when the connection was made.

This is the most general form of handler and it covers all the possible cases. However, it also expects the user to manually extract the needed values from the array of arguments. This is not always the most convenient solution. This is why GtkAda provides a second package related to signals, Gtk.Marshallers.

The Gtk.Marshallers package provides a set of functions that can be used as callbacks directly for GtkAda, and that will call your application’s handlers after extracting the required values from the array of arguments. Although this might sound somewhat complicated, in practice it simplifies the task of connecting signals. In fact, the techniques employed are similar to what is done internally by gtk+ in C. Because of the similarity of techniques, there is no overhead involved in using Gtk.Marshallers with Ada over the C code in gtk+.

A set of functions To_Marshaller is found in every generic package in Gtk.Handlers. They each take a single argument, the name of the function you want to call, and return a handler that can be used directly in Connect.

The connection is then done with the following piece of code:

Files_Cb.Object_Connect
  (Get_Ok_Button (Window),  --  The object to connect to the handler
   "clicked",               --  The name of the signal
   Files_Cb.To_Marshaller (Ok'Access),  --  The signal handler
   Slot_Object => Window);

Note that this can be done just after creating the widget, in the same block. As soon as it is created, a widget is ready to accept connections (although no signals will be emitted before the widget is shown on the screen).

We use To_Marshaller since our handler does not accept the array of arguments as a parameter, and we use the special Object_Connect procedure. This means that the parameter to our callback (Files) will be the Slot_Object given in Object_Connect, instead of being the button itself.


Previous: , Up: Signal handling   [Contents]

4.3 Handling user data

As described above, it is possible to define some data that is that passed to the callback when it is called. This data is called user_data, and is passed to the Connect or Object_Connect subprograms.

GtkAda will automatically free any memory it has allocated internally to store this user data. For instance, if you instantiated the generic package User_Callback with a String, it means that you want to be able to have a callback of the form:

   procedure My_Callback (Widget : access Gtk_Widget_Record'Class;
                           User_Data : String);

and connect it with a call similar to:

   Connect (Button, "Clicked", To_Marshaller (My_Callback'Access),
            User_Data => "any string");

GtkAda needs to allocate some memory to store the string (an unconstrained type). However, this memory is automatically freed when the callback is destroyed.

There are a few subtleties in the use of user_data, most importantly when the user data is itself a widget.

The following four examples do exactly the same thing: each creates two buttons, where clicking on the first one will destroy the second one. They all work fine the first time, while both buttons exist. However, some of them will fail if you press on the first button a second time.

Complete, compilable source code for these examples can be found in the distribution’s examples/user_data directory, from which the code samples below are excerpted.

4.3.1 First case: simple user data

This code will fail: even after Button2 is destroyed, the Ada pointer continues to reference memory that has been deallocated. The second call to Destroy will fail with a Storage_Error.

   package User_Callback is new Gtk.Handlers.User_Callback
     (Gtk_Widget_Record, Gtk_Widget);

   procedure My_Destroy2
     (Button : access Gtk_Widget_Record'Class; Data : Gtk_Widget) is
   begin
      Destroy (Data);
   end My_Destroy2;

   begin
      User_Callback.Connect
        (Button1, "clicked",
         User_Callback.To_Marshaller (My_Destroy2'Access),
         Gtk_Widget (Button2));
   end;

4.3.2 Second case: using Object_Connect instead

One of the solutions to fix the above problem is to use Object_Connect instead of Connect. In that case, GtkAda automatically takes care of disconnecting the callback when either of the two widgets is destroyed.

   procedure My_Destroy (Button : access Gtk_Widget_Record'Class) is
   begin
      Destroy (Button);
   end My_Destroy;

   begin
      Widget_Callback.Object_Connect
        (Button1, "clicked",
         Widget_Callback.To_Marshaller (My_Destroy'Access),
         Button2);
   end;

4.3.3 Third case: manually disconnecting the callback

Using Object_Connect is not always possible. In that case, one of the possibilities is to store the Id of the callback, and properly disconnect it when appropriate. This is the most complex method, and very often is not applicable, since you cannot know for sure when the callback is no longer needed.

   type My_Data3 is record
      Button, Object : Gtk_Widget;
      Id             : Handler_Id;
   end record;
   type My_Data3_Access is access My_Data3;

   package User_Callback3 is new Gtk.Handlers.User_Callback
     (Gtk_Widget_Record, My_Data3_Access);

   procedure My_Destroy3
     (Button : access Gtk_Widget_Record'Class;
      Data   : My_Data3_Access) is
   begin
      Destroy (Data.Button);
      Disconnect (Data.Object, Data.Id);
   end My_Destroy3;

      Id : Handler_Id;
   begin
      Data3 := new My_Data3' (Object => Gtk_Widget (Button1),
                              Button => Gtk_Widget (Button2),
                              Id     => (Null_Signal_Id, null));
      Id := User_Callback3.Connect
        (Button1, "clicked",
         User_Callback3.To_Marshaller (My_Destroy3'Access),
         Data3);
      Data3.Id := Id;
   end;

4.3.4 Fourth case: setting a watch on a specific widget

GtkAda provides a function Add_Watch, that will automatically disconnect a callback when a given widget is destroyed. This is the function used internally by Object_Connect. In the example below, the callback is automatically disconnected whenever Button2 is destroyed.

   procedure My_Destroy2
     (Button : access Gtk_Widget_Record'Class; Data : Gtk_Widget) is
   begin
      Destroy (Data);
   end My_Destroy2;

      Id : Handler_Id;
   begin
      Id := User_Callback.Connect
        (Button1, "clicked",
         User_Callback.To_Marshaller (My_Destroy2'Access),
         Gtk_Widget (Button2));
      Add_Watch (Id, Button2);
   end;

Next: , Previous:   [Contents]

5 Starting an application with GtkAda

You need to perform some initializations to start a GtkAda application:

--  predefined units of the library
with Gtk.Rc;
with Gtk.Main;
with Gtk.Enums;
with Gtk.Window;
...
--  My units
with Callbacks;
...
procedure Application is
   procedure Create_Window is ...

begin
   --  Set the locale specific datas (e.g time and date format)
   Gtk.Main.Set_Locale;

   --  Initializes GtkAda
   Gtk.Main.Init;

   --  Load the resources. Note that this part is optional.
   Gtk.Rc.Parse ("application.rc");

   --  Create the main window
   Create_Window;

   --  Signal handling loop
   Gtk.Main.Main;
end Application;

the Create_Window procedure looks like

   procedure Create_Window is
      Main_Window : Gtk.Window.Gtk_Window;
      ...
   begin
      Gtk.Window.Gtk_New
        (Window   => Main_Window,
         The_Type => Gtk.Enums.Window_Toplevel);

      --  From Gtk.Widget:
      Gtk.Window.Set_Title (Window => Main_Window, Title  => "Editor");

      --  Construct the window and connect various callbacks

      ...
      Gtk.Window.Show_All (Main_Window);
   end Create_Window;

Next: , Previous:   [Contents]

6 Resource files

Resource files let you parametrize aspects of the widgets in a GtkAda application without having to recompile it.

A resource file needs to be loaded (Gtk.Rc.Parse) before setting the corresponding window.

In this file, it is possible to specify visual characteristics of widgets, such as their colors and fonts. Under X, the xfontsel command allows you to easily select a font. The FontSelection widget is also a simple way to select fonts.

Here is an example of a resource file:

# application.rc
#
# resource file for "Application"

# Buttons style
style "button"
{
# BackGround Colors
#                  Red  Green  Blue
  bg[PRELIGHT] = { 0.0,  0.75, 0.0 } # Green when the mouse is on
                                     # the button
  bg[ACTIVE]   = { 0.75, 0.0,  0.0 } # Red on click
# ForeGround Colors
#                  Red  Green  Blue
  fg[PRELIGHT] = { 1.0,  1.0,  1.0 } # White when the mouse is on
                                     # the button
  fg[ACTIVE]   = { 1.0,  1.0,  1.0 } # White on click
}

# All the buttons will have the style "button"
widget_class "*GtkButton*" style "button"

# Text style
style "text"
{
  font = "-adobe-courier-medium-r-normal-*-15-*-*-*-*-*-*-*"
  text[NORMAL] = { 0.0, 0.0, 0.0 } # black
  fg[NORMAL]   = { 0.0, 0.0, 0.0 } # black
  base[NORMAL] = { 1.0, 1.0, 1.0 } # white : background color
}

# All Gtk_Text will have the "text" style
widget_class "*GtkText" style "text"

Next: , Previous:   [Contents]

7 Memory management

GtkAda takes care of almost all the memory management for you. Here is a brief overview of how this works, you’ll have to check the sources if you want more detailed information. Gtk+ (the C library) does its own memory management through reference counting, i.e. any widget is destroyed when it is no longer referenced anywhere in the application.

In GtkAda itself, a “user_data” is associated with each object allocated by a Gtk_New procedure. A “destroy” callback is also associated, to be called when the object to which the user_data belongs is destroyed. Thus, every time a C object is destroyed, the equivalent Ada structure is also destroyed (see Gtk.Free_User_Data).

Concerning widgets containing children, every container holds a reference to its children, whose reference counting is thus different from 0 (and generally 1). When the container is destroyed, the reference of all its children and grand-children is decremented, and they are destroyed in turn if needed. So the deallocation of a widget hierarchy is also performed automatically.


Next: , Previous:   [Contents]

8 Tasking with GtkAda

Note that Gtk+ under Windows does not interact properly with threads, so the only safe approach under this operating system is to perform all your Gtk+ calls in the same task.

On other platforms, the Glib library can be used in a task-safe mode by calling Gdk.Threads.G_Init and Gdk.Threads.Init before making any other Glib/Gdk calls. Gdk routines may then be called simultaneously by multiple tasks, thanks to task-safe construction of Gdk’s internal data structures. However, Gdk objects such as hash tables are not automatically protected, so it is the application’s responsibility to prevent simultaneous access to user-defined objects (e.g. by using protected objects).

When Gdk is initialized to be task-safe, GtkAda becomes task aware. There is a single global lock that you must acquire with Gdk.Threads.Enter before making any Gdk/Gtk call, and which you must release with Gdk.Threads.Leave afterwards.

Gtk.Main.Main should be called with the lock acquired (see example below), ensuring that all the functions executed in the task that started the main loop do not need to protect themselves again.

Beware that the GtkAda main loop (Gtk.Main.Main) can only be be run inside one specific task. In other words, you cannot call Gtk.Main.Main from any task other than the one that started the outer level main loop.

Note that Gdk.Threads assumes that you are using a tasking run time that maps Ada tasks to native threads.

A minimal main program for a tasking GtkAda application looks like:

with Gdk.Threads;
with Gtk.Main;
with Gtk.Enums; use Gtk.Enums;
with Gtk.Window; use Gtk.Window;

procedure GtkAda_With_Tasks is
   Window : Gtk_Window;
begin
   Gdk.Threads.G_Init;
   Gdk.Threads.Init;
   Gtk.Main.Init;

   Gtk_New (Window, Window_Toplevel);
   Show (Window);

   Gdk.Threads.Enter;
   Gtk.Main.Main;
   Gdk.Threads.Leave;
end GtkAda_With_Tasks;

Callbacks require a bit of attention. Callbacks from GtkAda (signals) are made within the GtkAda lock. However, callbacks from Glib (timeouts, IO callbacks, and idle functions) are made outside of the GtkAda lock. So, within a signal handler you do not need to call Gdk.Threads.Enter, but within the other types of callbacks, you do.


Next: , Previous:   [Contents]

9 Processing external events

It often happens that your application, in addition to processing graphical events through the GtkAda main loop, also needs to monitor external events. This is the case if, for instance, you are running external processes and need to display their output, or if you are listening to incoming data on a socket. If you implement your own main loop to poll for these external events and then invoke the GUI, the GUI will enter its main loop and not return control back to you.

There are several ways to handle this situation:


Next: , Previous:   [Contents]

10 Object-oriented features

GtkAda has been designed from the beginning to provide a full object oriented layer over gtk+. This means that features such as type extension and dynamic dispatching are made available through the standard Ada language.

This section will describe how things work, how you can extend existing widgets, and even how to create your own widgets.


Next: , Up: Object-oriented features   [Contents]

10.1 General description of the tagged types

10.1.1 Why should I use object-oriented programming ?

Every widget in the Gtk.* packages in GtkAda is a tagged type with a number of primitive subprograms that are inherited by all of its children. Tagged types in Ada make it possible to perform safe, automatic type conversions without using explicit casts (such as is necessary when coding in C). It is also possible for the compiler to verify whether or not these type conversions are valid. Most errors are found at compile time, which leads to a safer and more robust application.

As a further example, imagine a table that has been populated by some widgets. It is possible to query for this table’s children and operate on these widgets without knowing details about their type, their creator, and so on–the tagged objects that are returned contain all the information necessary. It becomes possible to use dynamic dispatching without ever having to cast to a known type.

Modifying a standard widget to draw itself differently or display different data is easy using tagged types. Simply create a new type that extends the current one (see the section Using tagged types to extend Gtk widgets below.

Creating a new reusable widget from scratch is also possible. Create a new tagged type and specify properties of the widget–such as how it is to draw itself and how it should react to events. See the section Creating new widgets in Ada below.

Object oriented programming through the use of Ada tagged types makes GtkAda a very powerful, flexible, and safe tool for designing graphical interfaces.

10.1.2 Type conversions from C to Ada widgets

There are three kinds of widgets that you can use with GtkAda:

GtkAda will always be able to find and/or create a valid tagged type in the first two cases, no matter if you explicitly created the widget or if it was created automatically by gtk+. For instance, if you created a widget in Ada, put it in a table, and later on extracted it from the table, then you will still have the same widget.

In the third case (third party C widgets), GtkAda is not, by default, able to create the corresponding Ada type.

The case of third party C widgets is a little bit trickier. Since GtkAda does not know anything about them when it is built, it can’t magically convert the C widgets to Ada widgets. This is your job to teach GtkAda how to do the conversion.

We thus provide a ’hook’ function which you need to modify. This function is defined in the package Glib.Type_Conversion. This function takes a string with the name of the C widget (ex/ "GtkButton"), and should return a newly allocated pointer. If you don’t know this type either, simply return null.


Next: , Previous: , Up: Object-oriented features   [Contents]

10.2 Using tagged types to extend Gtk widgets

With this toolkit, it’s possible to associate your own data with existing widgets simply by creating new types. This section will show you a simple example, but you should rather read the source code in the testgtk/ directory where we used this feature instead of using user_data as is used in the C version.

type My_Button_Record is new Gtk_Button_Record with record
    --  whatever data you want to associate with your button
end record;
type My_Button is access all My_Button_Record'Class;

With the above statements, your new type is defined. Every function available for Gtk_Button is also available for My_Button. Of course, as with every tagged type in Ada, you can create your own primitive functions with the following prototype:

procedure My_Primitive_Func (Myb : access My_Button_Record);

To instanciate an object of type My_Button in your application, do the following:

declare
   Myb : My_Button;
begin
   Myb := new My_Button_Record;
   Initialize (Myb);   --  from Gtk.Button
end;

The first line creates the Ada type, whereas the Initialize call actually creates the C widget and associates it with the Ada type.


Previous: , Up: Object-oriented features   [Contents]

10.3 Creating new widgets in Ada

With GtkAda, you can create widgets directly in Ada. These new widgets can be used directly, as if they were part of gtk itself.

Creating new widgets is a way to create reuseable components. You can apply to them the same functions as you would for any other widget, such as Show, Hide, and so on.

This section will explain how to create two types of widgets: composite widgets and widgets created from scratch. Two examples are provided with GtkAda, in the directories examples/composite_widget and examples/base_widget. Please also refer to the gtk+ tutorial, which describes the basic mechanisms that you need to know to create a widget.


Next: , Up: Creating new widgets in Ada   [Contents]

10.3.1 Creating composite widgets

A composite widget is a widget that does not do much by itself. Rather, this is a collection of subwidgets grouped into a more general entity. For instance, among the standard widgets, Gtk_File_Selection and Gtk_Font_Selection belong to this category.

The good news is that there is nothing special to know. Just create a new tagged type, extending one of the standard widgets (or even another of your own widgets), provide a Gtk_New function that allocates memory for this widget, and call the Initialize function that does the actual creation of the widget and the subwidgets. There is only one thing to do: Initialize should call the parent class’s Initialize function, to create the underlying C widget.

The example directory examples/composite_widget reimplements the Gtk_Dialog widget as written in C by the creators of gtk+.


Previous: , Up: Creating new widgets in Ada   [Contents]

10.3.2 Creating widgets from scratch

Creating a working widget from scratch requires a certain level of familiary with the GtkAda signal mechanism and entails much work with low level signals. This is therefore not an activity recommended for novice GtkAda programmers.

Creating a widget from scratch is what you want to do if your widget should be drawn in a special way, should create and emit new signals, or otherwise perform differently than pre-existing widgets. The example we give in examples/base_widget is a small target on which the user can click, and that sends one of two signals: "bullseye" or "missed", depending on where the user has clicked.

See also the example in examples/tutorial/gtkdial for a more complex widget, that implements a gauge where the user can move the arrow to select a new value.

Once again, the only two functions that you must create are Gtk_New and Initialize. This time, Initialize has to do two things:

Parent_Package.Initialize (Widget);

--  The above line calls the Initialize function from the parent.
--  This creates the underlying C widget, which we are going to
--  modify with the following call:

Gtk.Object.Initialize_Class_Record
  (Widget, Signals, Class_Record);
--  This initializes the "class record" for the widget and
--  creates the signals.

In the above example, the new part is the second call. It takes three or four arguments:

Then of course Initialize should set up some signal handlers for the functions you want to redefine. Three signals are especially useful:


Next: , Previous:   [Contents]

11 Support for Glade, the Gtk GUI builder

11.1 Introduction

GtkAda now comes with support for the GUI builder Glade-3. Glade-3 provides a graphical interface for designing windows and dialogs. The interface description is saved in an XML file which can be loaded at run-time by your GtkAda application. With this approach, there is no need to write or generate Ada code to describe the interface, all is needed is to write the callbacks for various actions.

11.2 Launching Glade

Under UNIX and Linux, Glade is invoked by the command-line script glade-3 which is located in the bin directory of your GtkAda installation. Under Windows, Glade is invoked by clicking on the executable glade-3.exe, also located in the bin directory of your GtkAda installation.

11.3 Building your interface

In Glade-3 the interface is done by point-and-clicking. The first step is to create one or more toplevel window and then placing widgets in these windows.

Detailed tutorials can be found at: http://live.gnome.org/Glade/Tutorials

In the Preferences for your project (menu Edit->Preferences), make sure that the preference "Project file format" is set to "GtkBuilder".

11.4 Using the interface in your application.

Once the interface is built and saved in an XML file, you can use it in your GtkAda application. You will need to use objects defined in the package Gtkada.Builder to load the interface file and to connect subprograms defined in your application to signals emitted by the interface. See the detailed explanations and examples in gtkada-builder.ads


Next: , Previous:   [Contents]

12 Binding new widgets

GtkAda comes with a Perl script to help you create a binding to a C widget (this is the script we have used ourselves). This will not fully automate the process, although it should really speed things up. You will probably need less than 15 min to create a new binding once you will get used to the way GtkAda works. Note that your C file should have the same format as is used by Gtk+ itself.

To get started on a new binding, launch the script contrib/binding.pl as follows:

$ touch gtk-button.ads
$ binding.pl ../include/gtk/gtkbutton.h > temporary

This dumps several kind of information on the standard output:

You can also use this script to update existing bindings:

$ binding.pl ../include/gtk/*.h

Next: , Previous:   [Contents]

13 Debugging GtkAda applications

This chapter presents a number of technics that can be used when debugging GtkAda applications. First, the standard tools to debug Ada applications can be used:

Compile with -g

You should almost always include debugging information when compiling and linking your code. This gives you the possibility to use the debugger. See below the variable GDK_DEBUG for how to disable grabs.

bind with -E

Using this argument on the gnatbind or gnatmake command line will force the compiler to include backtraces when an exception is raised. These backtraces can be converted to symbolic backtraces by using the addr2line tool.

Link with -lgmem

Using this switch gives access to the gnatmem tool, that helps you to detect memory leaks or doubly-deallocated memory. The latter often results in hard-to-fix Storage_Error exceptions. See the GNAT User’s guide for more information.

There are also a number of technics specific to GtkAda or gtk+ applications. For most of them, you might need to recompile these libraries with the appropriate switches to get access to the extended debugging features.

Use the --sync switch

Under unix systems, all applications compiled with gtk+ automatically support this switch, which forces events to be processed synchronously, thus making it easier to detect problems as soon as they happen. This switch is not relevant to Windows systems.

break on g_log

In the debugger, it is often useful to put a breakpoint on the glib function g_log. When gtk+ is linked dynamically, you will need to first start your application with begin, then put the breakpoint and continue the application with cont. This helps understand internal errors or warnings reported by gtk+ and glib

compile glib with --disable-mem-pools

Glib, the underlying layer that provides system-independent services to gtk+, has an extensive and optimized system for memory allocation. Bigger chunks of Memory are allocated initially, and then subdivided by glib itself. Although this is extremely performant, this also make the debugging of memory-related problems (storage_error) more difficult. Compiling with the above switch forces glib to use the standard malloc() and free() system calls. On GNU/Linux systems, it might be useful to set the variable MALLOC_CHECK_ to 1 to use error-detecting algorithms (see the man page for malloc()).

compile glib and gtk+ with --enable-debug=yes

It is recommended that you specify this switch on the configure command line when compiling these two libraries. In addition to compiling the libraries with debugging information for the debugger, additional runtime debug options (controllable via environment variables) become available. Specifying --enable-debug=no is not recommended for production releases (see glib or gtk+ documentation for details).

For these three variables, the possible values are given below. These are lists of colon-separated keywords. You can choose to remove any of these value from the variable

GOBJECT_DEBUG=objects:signals

This sets up the debugging output for glib. The value ‘objects’ is probably the most useful, and displays, on exit of the application, the list of unfreed objects. This helps detect memory leaks. The second value ‘signals’ will display all the signals emitted by the objects. Note that this results in a significant amount of output.

GDK_DEBUG=updates:nograbs:events:dnd:misc:
xim:colormap:gdkrgb:gc:pixmap:image:input:cursor

This sets up the debugging output for gdk. The most useful value is ‘nograbs’, which prevents the application from ever grabbing the mouse or keyboards. If you don’t set this, it might happen that the debugger becomes unusable, since you don’t have access to the mouse when the debugger stops on a breakpoint. Another simpler solution is to debug remotely from another machine, in which case the grabs won’t affect the terminal on which the debugger is running.

GTK_DEBUG=misc:plugsocket:text:tree:updates:keybindings

This sets up the debugging output for gtk. Almost all of these values are mostly for internal use by gtk+ developpers, although ‘keybindings’ might prove useful sometimes.

Import the C function ada_gtk_debug_get_ref_count

This function has the following Ada profile:

function Ref_Count (Add : System.Address) return Guint;
pragma Import (C, Ref_Count, "ada_gtk_debug_get_ref_count");

and should be called in a manner similar to

declare
   Widget : Gtk_Widget;
   Count  : Guint;
begin
   Count := Ref_Count (Get_Object (Widget));
end;

and returns the internal reference counter for the widget. When this counter reaches 0, the memory allocated for the widget is automatically freed.

This is mostly a debugging aid for people writting their own containers, and shouldn’t generally be needed. You shouldn’t rely on the internal reference counter in your actual code, which is why it isn’t exported by default in GtkAda.


Next: , Previous:   [Contents]

14 How to report bugs

GtkAda is a mature, stable toolkit that is heavily and widely used on a variety of platforms. We test GtkAda using an Ada version of the testgtk.c file found in the gtk+ distribution, as well as by generating a significant number of interfaces using the GUI builder and Gate. For code examples that demonstrate the use of this toolkit, look within the testgtk/ directory.

There are two kinds of problems you can encounter:

If you are a supported user of GNAT, send mail to mailto:report@gnat.com to report errors, otherwise send mail to the GtkAda list (mailto:gtkada@lists.adacore.com) explaining exactly what your are doing, what is the expected result and what you actually get. Please include the required sources to reproduce the problem, in a format usable by gnatchop (basically, insert all the required sources at the end of the mail). Please try to provide as small as possible a subset of your sources.

Of course, we will welcome any patch you can provide, so that this toolkit may be as useful as possible.


Next: , Previous:   [Contents]

15 Bibliography

We recommand the following documents. Most of them were written with C in mind, but should be easily adapted after you’ve read the rest of this document.


Previous:   [Contents]

Appendix A GNU General Public License

		    GNU GENERAL PUBLIC LICENSE
		       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

		    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

			    NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

		     END OF TERMS AND CONDITIONS

	    How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) 19yy  <name of author>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) 19yy name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.

Table of Contents