GTK v1.2 Tutorial: Code Examples

Next Previous Contents

## 30. Code Examples

Below are the code examples that are used in the above text which are not included in complete form elsewhere.

## 30.1 Tictactoe

### tictactoe.h

> `

>     /* example-start tictactoe tictactoe.h */

>     /* GTK - The GIMP Toolkit
>      * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
>      *
>      * This library is free software; you can redistribute it and/or
>      * modify it under the terms of the GNU Library General Public
>      * License as published by the Free Software Foundation; either
>      * version 2 of the License, or (at your option) any later version.
>      *
>      * This library 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
>      * Library General Public License for more details.
>      *
>      * You should have received a copy of the GNU Library General Public
>      * License along with this library; if not, write to the
>      * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
>      * Boston, MA 02111-1307, USA.
>      */
>     #ifndef __TICTACTOE_H__
>     #define __TICTACTOE_H__

>     #include <gdk/gdk.h>
>     #include <gtk/gtkvbox.h>

>     #ifdef __cplusplus
>     extern "C" {
>     #endif /* __cplusplus */

>     #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
>     #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
>     #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())

>     typedef struct _Tictactoe       Tictactoe;
>     typedef struct _TictactoeClass  TictactoeClass;

>     struct _Tictactoe
>     {
>       GtkVBox vbox;

>       GtkWidget *buttons[3][3];
>     };

>     struct _TictactoeClass
>     {
>       GtkVBoxClass parent_class;

>       void (* tictactoe) (Tictactoe *ttt);
>     };

>     guint          tictactoe_get_type        (void);
>     GtkWidget*     tictactoe_new             (void);
>     void           tictactoe_clear           (Tictactoe *ttt);

>     #ifdef __cplusplus
>     }
>     #endif /* __cplusplus */

>     #endif /* __TICTACTOE_H__ */

>     /* example-end */

> `

### tictactoe.c

> `

>     /* example-start tictactoe tictactoe.c */

>     /* GTK - The GIMP Toolkit
>      * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
>      *
>      * This library is free software; you can redistribute it and/or
>      * modify it under the terms of the GNU Library General Public
>      * License as published by the Free Software Foundation; either
>      * version 2 of the License, or (at your option) any later version.
>      *
>      * This library 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
>      * Library General Public License for more details.
>      *
>      * You should have received a copy of the GNU Library General Public
>      * License along with this library; if not, write to the
>      * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
>      * Boston, MA 02111-1307, USA.
>      */
>     #include "gtk/gtksignal.h"
>     #include "gtk/gtktable.h"
>     #include "gtk/gtktogglebutton.h"
>     #include "tictactoe.h"

>     enum {
>       TICTACTOE_SIGNAL,
>       LAST_SIGNAL
>     };

>     static void tictactoe_class_init          (TictactoeClass *klass);
>     static void tictactoe_init                (Tictactoe      *ttt);
>     static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);

>     static gint tictactoe_signals[LAST_SIGNAL] = { 0 };

>     guint
>     tictactoe_get_type ()
>     {
>       static guint ttt_type = 0;

>       if (!ttt_type)
>         {
>           GtkTypeInfo ttt_info =
>           {
>             "Tictactoe",
>             sizeof (Tictactoe),
>             sizeof (TictactoeClass),
>             (GtkClassInitFunc) tictactoe_class_init,
>             (GtkObjectInitFunc) tictactoe_init,
>             (GtkArgSetFunc) NULL,
>             (GtkArgGetFunc) NULL
>           };

>           ttt_type = gtk_type_unique (gtk_vbox_get_type (), &ttt_info);
>         }

>       return ttt_type;
>     }

>     static void
>     tictactoe_class_init (TictactoeClass *class)
>     {
>       GtkObjectClass *object_class;

>       object_class = (GtkObjectClass*) class;

>       tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
>                                              GTK_RUN_FIRST,
>                                              object_class->type,
>                                              GTK_SIGNAL_OFFSET (TictactoeClass,
>                                                                 tictactoe),
>                                              gtk_signal_default_marshaller,
>                                              GTK_TYPE_NONE, 0);

>       gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);

>       class->tictactoe = NULL;
>     }

>     static void
>     tictactoe_init (Tictactoe *ttt)
>     {
>       GtkWidget *table;
>       gint i,j;

>       table = gtk_table_new (3, 3, TRUE);
>       gtk_container_add (GTK_CONTAINER(ttt), table);
>       gtk_widget_show (table);

>       for (i=0;i<3; i++)
>         for (j=0;j<3; j++)
>           {
>             ttt->buttons[i][j] = gtk_toggle_button_new ();
>             gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j],
>                                        i, i+1, j, j+1);
>             gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
>                                 GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
>             gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
>             gtk_widget_show (ttt->buttons[i][j]);
>           }
>     }

>     GtkWidget*
>     tictactoe_new ()
>     {
>       return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
>     }

>     void
>     tictactoe_clear (Tictactoe *ttt)
>     {
>       int i,j;

>       for (i=0;i<3;i++)
>         for (j=0;j<3;j++)
>           {
>             gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
>             gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
>                                          FALSE);
>             gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
>           }
>     }

>     static void
>     tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
>     {
>       int i,k;

>       static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
>                                  { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
>                                  { 0, 1, 2 }, { 0, 1, 2 } };
>       static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
>                                  { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
>                                  { 0, 1, 2 }, { 2, 1, 0 } };

>       int success, found;

>       for (k=0; k<8; k++)
>         {
>           success = TRUE;
>           found = FALSE;

>           for (i=0;i<3;i++)
>             {
>               success = success &&
>                 GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
>               found = found ||
>                 ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
>             }

>           if (success && found)
>             {
>               gtk_signal_emit (GTK_OBJECT (ttt),
>                                tictactoe_signals[TICTACTOE_SIGNAL]);
>               break;
>             }
>         }
>     }

>     /* example-end */

> `

### ttt_test.c

> `

>     /* example-start tictactoe ttt_test.c */

>     #include <gtk/gtk.h>
>     #include "tictactoe.h"

>     void win( GtkWidget *widget,
>               gpointer   data )
>     {
>       g_print ("Yay!\n");
>       tictactoe_clear (TICTACTOE (widget));
>     }

>     int main( int   argc,
>               char *argv[] )
>     {
>       GtkWidget *window;
>       GtkWidget *ttt;

>       gtk_init (&argc, &argv);

>       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

>       gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");

>       gtk_signal_connect (GTK_OBJECT (window), "destroy",
>                           GTK_SIGNAL_FUNC (gtk_exit), NULL);

>       gtk_container_set_border_width (GTK_CONTAINER (window), 10);

>       ttt = tictactoe_new ();

>       gtk_container_add (GTK_CONTAINER (window), ttt);
>       gtk_widget_show (ttt);

>       gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
>                           GTK_SIGNAL_FUNC (win), NULL);

>       gtk_widget_show (window);

>       gtk_main ();

>       return 0;
>     }

>     /* example-end */

> `

## 30.2 GtkDial

### gtkdial.h

> `

>     /* example-start gtkdial gtkdial.h */

>     /* GTK - The GIMP Toolkit
>      * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
>      *
>      * This library is free software; you can redistribute it and/or
>      * modify it under the terms of the GNU Library General Public
>      * License as published by the Free Software Foundation; either
>      * version 2 of the License, or (at your option) any later version.
>      *
>      * This library 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
>      * Library General Public License for more details.
>      *
>      * You should have received a copy of the GNU Library General Public
>      * License along with this library; if not, write to the
>      * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
>      * Boston, MA 02111-1307, USA.
>      */
>     #ifndef __GTK_DIAL_H__
>     #define __GTK_DIAL_H__

>     #include <gdk/gdk.h>
>     #include <gtk/gtkadjustment.h>
>     #include <gtk/gtkwidget.h>

>     #ifdef __cplusplus
>     extern "C" {
>     #endif /* __cplusplus */

>     #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
>     #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
>     #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())

>     typedef struct _GtkDial        GtkDial;
>     typedef struct _GtkDialClass   GtkDialClass;

>     struct _GtkDial
>     {
>       GtkWidget widget;

>       /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
>       guint policy : 2;

>       /* Button currently pressed or 0 if none */
>       guint8 button;

>       /* Dimensions of dial components */
>       gint radius;
>       gint pointer_width;

>       /* ID of update timer, or 0 if none */
>       guint32 timer;

>       /* Current angle */
>       gfloat angle;
>       gfloat last_angle;

>       /* Old values from adjustment stored so we know when something changes */
>       gfloat old_value;
>       gfloat old_lower;
>       gfloat old_upper;

>       /* The adjustment object that stores the data for this dial */
>       GtkAdjustment *adjustment;
>     };

>     struct _GtkDialClass
>     {
>       GtkWidgetClass parent_class;
>     };

>     GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
>     guint          gtk_dial_get_type               (void);
>     GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
>     void           gtk_dial_set_update_policy      (GtkDial      *dial,
>                                                     GtkUpdateType  policy);

>     void           gtk_dial_set_adjustment         (GtkDial      *dial,
>                                                     GtkAdjustment *adjustment);
>     #ifdef __cplusplus
>     }
>     #endif /* __cplusplus */

>     #endif /* __GTK_DIAL_H__ */
>     /* example-end */

> `

### gtkdial.c

> `

>     /* example-start gtkdial gtkdial.c */

>     /* GTK - The GIMP Toolkit
>      * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
>      *
>      * This library is free software; you can redistribute it and/or
>      * modify it under the terms of the GNU Library General Public
>      * License as published by the Free Software Foundation; either
>      * version 2 of the License, or (at your option) any later version.
>      *
>      * This library 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
>      * Library General Public License for more details.
>      *
>      * You should have received a copy of the GNU Library General Public
>      * License along with this library; if not, write to the
>      * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
>      * Boston, MA 02111-1307, USA.
>      */
>     #include <math.h>
>     #include <stdio.h>
>     #include <gtk/gtkmain.h>
>     #include <gtk/gtksignal.h>

>     #include "gtkdial.h"

>     #define SCROLL_DELAY_LENGTH  300
>     #define DIAL_DEFAULT_SIZE 100

>     /* Forward declarations */

>     static void gtk_dial_class_init               (GtkDialClass    *klass);
>     static void gtk_dial_init                     (GtkDial         *dial);
>     static void gtk_dial_destroy                  (GtkObject        *object);
>     static void gtk_dial_realize                  (GtkWidget        *widget);
>     static void gtk_dial_size_request             (GtkWidget      *widget,
>                                                    GtkRequisition *requisition);
>     static void gtk_dial_size_allocate            (GtkWidget     *widget,
>                                                    GtkAllocation *allocation);
>     static gint gtk_dial_expose                   (GtkWidget        *widget,
>                                                     GdkEventExpose   *event);
>     static gint gtk_dial_button_press             (GtkWidget        *widget,
>                                                     GdkEventButton   *event);
>     static gint gtk_dial_button_release           (GtkWidget        *widget,
>                                                     GdkEventButton   *event);
>     static gint gtk_dial_motion_notify            (GtkWidget        *widget,
>                                                     GdkEventMotion   *event);
>     static gint gtk_dial_timer                    (GtkDial         *dial);

>     static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
>     static void gtk_dial_update                   (GtkDial *dial);
>     static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
>                                                     gpointer          data);
>     static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
>                                                     gpointer          data);

>     /* Local data */

>     static GtkWidgetClass *parent_class = NULL;

>     guint
>     gtk_dial_get_type ()
>     {
>       static guint dial_type = 0;

>       if (!dial_type)
>         {
>           GtkTypeInfo dial_info =
>           {
>             "GtkDial",
>             sizeof (GtkDial),
>             sizeof (GtkDialClass),
>             (GtkClassInitFunc) gtk_dial_class_init,
>             (GtkObjectInitFunc) gtk_dial_init,
>             (GtkArgSetFunc) NULL,
>             (GtkArgGetFunc) NULL,
>           };

>           dial_type = gtk_type_unique (gtk_widget_get_type (), &dial_info);
>         }

>       return dial_type;
>     }

>     static void
>     gtk_dial_class_init (GtkDialClass *class)
>     {
>       GtkObjectClass *object_class;
>       GtkWidgetClass *widget_class;

>       object_class = (GtkObjectClass*) class;
>       widget_class = (GtkWidgetClass*) class;

>       parent_class = gtk_type_class (gtk_widget_get_type ());

>       object_class->destroy = gtk_dial_destroy;

>       widget_class->realize = gtk_dial_realize;
>       widget_class->expose_event = gtk_dial_expose;
>       widget_class->size_request = gtk_dial_size_request;
>       widget_class->size_allocate = gtk_dial_size_allocate;
>       widget_class->button_press_event = gtk_dial_button_press;
>       widget_class->button_release_event = gtk_dial_button_release;
>       widget_class->motion_notify_event = gtk_dial_motion_notify;
>     }

>     static void
>     gtk_dial_init (GtkDial *dial)
>     {
>       dial->button = 0;
>       dial->policy = GTK_UPDATE_CONTINUOUS;
>       dial->timer = 0;
>       dial->radius = 0;
>       dial->pointer_width = 0;
>       dial->angle = 0.0;
>       dial->old_value = 0.0;
>       dial->old_lower = 0.0;
>       dial->old_upper = 0.0;
>       dial->adjustment = NULL;
>     }

>     GtkWidget*
>     gtk_dial_new (GtkAdjustment *adjustment)
>     {
>       GtkDial *dial;

>       dial = gtk_type_new (gtk_dial_get_type ());

>       if (!adjustment)
>         adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);

>       gtk_dial_set_adjustment (dial, adjustment);

>       return GTK_WIDGET (dial);
>     }

>     static void
>     gtk_dial_destroy (GtkObject *object)
>     {
>       GtkDial *dial;

>       g_return_if_fail (object != NULL);
>       g_return_if_fail (GTK_IS_DIAL (object));

>       dial = GTK_DIAL (object);

>       if (dial->adjustment)
>         gtk_object_unref (GTK_OBJECT (dial->adjustment));

>       if (GTK_OBJECT_CLASS (parent_class)->destroy)
>         (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
>     }

>     GtkAdjustment*
>     gtk_dial_get_adjustment (GtkDial *dial)
>     {
>       g_return_val_if_fail (dial != NULL, NULL);
>       g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);

>       return dial->adjustment;
>     }

>     void
>     gtk_dial_set_update_policy (GtkDial      *dial,
>                                  GtkUpdateType  policy)
>     {
>       g_return_if_fail (dial != NULL);
>       g_return_if_fail (GTK_IS_DIAL (dial));

>       dial->policy = policy;
>     }

>     void
>     gtk_dial_set_adjustment (GtkDial      *dial,
>                               GtkAdjustment *adjustment)
>     {
>       g_return_if_fail (dial != NULL);
>       g_return_if_fail (GTK_IS_DIAL (dial));

>       if (dial->adjustment)
>         {
>           gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
>           gtk_object_unref (GTK_OBJECT (dial->adjustment));
>         }

>       dial->adjustment = adjustment;
>       gtk_object_ref (GTK_OBJECT (dial->adjustment));

>       gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
>                           (GtkSignalFunc) gtk_dial_adjustment_changed,
>                           (gpointer) dial);
>       gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
>                           (GtkSignalFunc) gtk_dial_adjustment_value_changed,
>                           (gpointer) dial);

>       dial->old_value = adjustment->value;
>       dial->old_lower = adjustment->lower;
>       dial->old_upper = adjustment->upper;

>       gtk_dial_update (dial);
>     }

>     static void
>     gtk_dial_realize (GtkWidget *widget)
>     {
>       GtkDial *dial;
>       GdkWindowAttr attributes;
>       gint attributes_mask;

>       g_return_if_fail (widget != NULL);
>       g_return_if_fail (GTK_IS_DIAL (widget));

>       GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
>       dial = GTK_DIAL (widget);

>       attributes.x = widget->allocation.x;
>       attributes.y = widget->allocation.y;
>       attributes.width = widget->allocation.width;
>       attributes.height = widget->allocation.height;
>       attributes.wclass = GDK_INPUT_OUTPUT;
>       attributes.window_type = GDK_WINDOW_CHILD;
>       attributes.event_mask = gtk_widget_get_events (widget) |
>         GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
>         GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
>         GDK_POINTER_MOTION_HINT_MASK;
>       attributes.visual = gtk_widget_get_visual (widget);
>       attributes.colormap = gtk_widget_get_colormap (widget);

>       attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
>       widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);

>       widget->style = gtk_style_attach (widget->style, widget->window);

>       gdk_window_set_user_data (widget->window, widget);

>       gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
>     }

>     static void
>     gtk_dial_size_request (GtkWidget      *widget,
>                            GtkRequisition *requisition)
>     {
>       requisition->width = DIAL_DEFAULT_SIZE;
>       requisition->height = DIAL_DEFAULT_SIZE;
>     }

>     static void
>     gtk_dial_size_allocate (GtkWidget     *widget,
>                             GtkAllocation *allocation)
>     {
>       GtkDial *dial;

>       g_return_if_fail (widget != NULL);
>       g_return_if_fail (GTK_IS_DIAL (widget));
>       g_return_if_fail (allocation != NULL);

>       widget->allocation = *allocation;
>       dial = GTK_DIAL (widget);

>       if (GTK_WIDGET_REALIZED (widget))
>         {

>           gdk_window_move_resize (widget->window,
>                                   allocation->x, allocation->y,
>                                   allocation->width, allocation->height);

>         }
>       dial->radius = MIN(allocation->width,allocation->height) * 0.45;
>       dial->pointer_width = dial->radius / 5;
>     }

>     static gint
>     gtk_dial_expose (GtkWidget      *widget,
>                      GdkEventExpose *event)
>     {
>       GtkDial *dial;
>       GdkPoint points[6];
>       gdouble s,c;
>       gdouble theta, last, increment;
>       GtkStyle      *blankstyle;
>       gint xc, yc;
>       gint upper, lower;
>       gint tick_length;
>       gint i, inc;

>       g_return_val_if_fail (widget != NULL, FALSE);
>       g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
>       g_return_val_if_fail (event != NULL, FALSE);

>       if (event->count > 0)
>         return FALSE;

>       dial = GTK_DIAL (widget);

>     /*  gdk_window_clear_area (widget->window,
>                              0, 0,
>                              widget->allocation.width,
>                              widget->allocation.height);
>     */
>       xc = widget->allocation.width/2;
>       yc = widget->allocation.height/2;

>       upper = dial->adjustment->upper;
>       lower = dial->adjustment->lower;

>       /* Erase old pointer */

>       s = sin(dial->last_angle);
>       c = cos(dial->last_angle);
>       dial->last_angle = dial->angle;

>       points[0].x = xc + s*dial->pointer_width/2;
>       points[0].y = yc + c*dial->pointer_width/2;
>       points[1].x = xc + c*dial->radius;
>       points[1].y = yc - s*dial->radius;
>       points[2].x = xc - s*dial->pointer_width/2;
>       points[2].y = yc - c*dial->pointer_width/2;
>       points[3].x = xc - c*dial->radius/10;
>       points[3].y = yc + s*dial->radius/10;
>       points[4].x = points[0].x;
>       points[4].y = points[0].y;

>       blankstyle = gtk_style_new ();
>       blankstyle->bg_gc[GTK_STATE_NORMAL] =
>                     widget->style->bg_gc[GTK_STATE_NORMAL];
>       blankstyle->dark_gc[GTK_STATE_NORMAL] =
>                     widget->style->bg_gc[GTK_STATE_NORMAL];
>       blankstyle->light_gc[GTK_STATE_NORMAL] =
>                     widget->style->bg_gc[GTK_STATE_NORMAL];
>       blankstyle->black_gc =
>                     widget->style->bg_gc[GTK_STATE_NORMAL];

>       gtk_draw_polygon (blankstyle,
>                         widget->window,
>                         GTK_STATE_NORMAL,
>                         GTK_SHADOW_OUT,
>                         points, 5,
>                         FALSE);

>       gtk_style_unref(blankstyle);

>       /* Draw ticks */

>       if ((upper - lower) == 0)
>         return;

>       increment = (100*M_PI)/(dial->radius*dial->radius);

>       inc = (upper - lower);

>       while (inc < 100) inc *=10;
>       while (inc >= 1000) inc /=10;
>       last = -1;

>       for (i=0; i<=inc; i++)
>         {
>           theta = ((gfloat)i*M_PI/(18*inc/24.) - M_PI/6.);

>           if ((theta - last) < (increment))
>             continue;
>           last = theta;

>           s = sin(theta);
>           c = cos(theta);

>           tick_length = (i%(inc/10) == 0) ? dial->pointer_width : dial->pointer_width/2;

>           gdk_draw_line (widget->window,
>                          widget->style->fg_gc[widget->state],
>                          xc + c*(dial->radius - tick_length),
>                          yc - s*(dial->radius - tick_length),
>                          xc + c*dial->radius,
>                          yc - s*dial->radius);
>         }

>       /* Draw pointer */

>       s = sin(dial->angle);
>       c = cos(dial->angle);
>       dial->last_angle = dial->angle;

>       points[0].x = xc + s*dial->pointer_width/2;
>       points[0].y = yc + c*dial->pointer_width/2;
>       points[1].x = xc + c*dial->radius;
>       points[1].y = yc - s*dial->radius;
>       points[2].x = xc - s*dial->pointer_width/2;
>       points[2].y = yc - c*dial->pointer_width/2;
>       points[3].x = xc - c*dial->radius/10;
>       points[3].y = yc + s*dial->radius/10;
>       points[4].x = points[0].x;
>       points[4].y = points[0].y;

>       gtk_draw_polygon (widget->style,
>                         widget->window,
>                         GTK_STATE_NORMAL,
>                         GTK_SHADOW_OUT,
>                         points, 5,
>                         TRUE);

>       return FALSE;
>     }

>     static gint
>     gtk_dial_button_press (GtkWidget      *widget,
>                            GdkEventButton *event)
>     {
>       GtkDial *dial;
>       gint dx, dy;
>       double s, c;
>       double d_parallel;
>       double d_perpendicular;

>       g_return_val_if_fail (widget != NULL, FALSE);
>       g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
>       g_return_val_if_fail (event != NULL, FALSE);

>       dial = GTK_DIAL (widget);

>       /* Determine if button press was within pointer region - we
>          do this by computing the parallel and perpendicular distance of
>          the point where the mouse was pressed from the line passing through
>          the pointer */

>       dx = event->x - widget->allocation.width / 2;
>       dy = widget->allocation.height / 2 - event->y;

>       s = sin(dial->angle);
>       c = cos(dial->angle);

>       d_parallel = s*dy + c*dx;
>       d_perpendicular = fabs(s*dx - c*dy);

>       if (!dial->button &&
>           (d_perpendicular < dial->pointer_width/2) &&
>           (d_parallel > - dial->pointer_width))
>         {
>           gtk_grab_add (widget);

>           dial->button = event->button;

>           gtk_dial_update_mouse (dial, event->x, event->y);
>         }

>       return FALSE;
>     }

>     static gint
>     gtk_dial_button_release (GtkWidget      *widget,
>                               GdkEventButton *event)
>     {
>       GtkDial *dial;

>       g_return_val_if_fail (widget != NULL, FALSE);
>       g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
>       g_return_val_if_fail (event != NULL, FALSE);

>       dial = GTK_DIAL (widget);

>       if (dial->button == event->button)
>         {
>           gtk_grab_remove (widget);

>           dial->button = 0;

>           if (dial->policy == GTK_UPDATE_DELAYED)
>             gtk_timeout_remove (dial->timer);

>           if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
>               (dial->old_value != dial->adjustment->value))
>             gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
>         }

>       return FALSE;
>     }

>     static gint
>     gtk_dial_motion_notify (GtkWidget      *widget,
>                              GdkEventMotion *event)
>     {
>       GtkDial *dial;
>       GdkModifierType mods;
>       gint x, y, mask;

>       g_return_val_if_fail (widget != NULL, FALSE);
>       g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
>       g_return_val_if_fail (event != NULL, FALSE);

>       dial = GTK_DIAL (widget);

>       if (dial->button != 0)
>         {
>           x = event->x;
>           y = event->y;

>           if (event->is_hint || (event->window != widget->window))
>             gdk_window_get_pointer (widget->window, &x, &y, &mods);

>           switch (dial->button)
>             {
>             case 1:
>               mask = GDK_BUTTON1_MASK;
>               break;
>             case 2:
>               mask = GDK_BUTTON2_MASK;
>               break;
>             case 3:
>               mask = GDK_BUTTON3_MASK;
>               break;
>             default:
>               mask = 0;
>               break;
>             }

>           if (mods & mask)
>             gtk_dial_update_mouse (dial, x,y);
>         }

>       return FALSE;
>     }

>     static gint
>     gtk_dial_timer (GtkDial *dial)
>     {
>       g_return_val_if_fail (dial != NULL, FALSE);
>       g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);

>       if (dial->policy == GTK_UPDATE_DELAYED)
>         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");

>       return FALSE;
>     }

>     static void
>     gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
>     {
>       gint xc, yc;
>       gfloat old_value;

>       g_return_if_fail (dial != NULL);
>       g_return_if_fail (GTK_IS_DIAL (dial));

>       xc = GTK_WIDGET(dial)->allocation.width / 2;
>       yc = GTK_WIDGET(dial)->allocation.height / 2;

>       old_value = dial->adjustment->value;
>       dial->angle = atan2(yc-y, x-xc);

>       if (dial->angle < -M_PI/2.)
>         dial->angle += 2*M_PI;

>       if (dial->angle < -M_PI/6)
>         dial->angle = -M_PI/6;

>       if (dial->angle > 7.*M_PI/6.)
>         dial->angle = 7.*M_PI/6.;

>       dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
>         (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);

>       if (dial->adjustment->value != old_value)
>         {
>           if (dial->policy == GTK_UPDATE_CONTINUOUS)
>             {
>               gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
>             }
>           else
>             {
>               gtk_widget_draw (GTK_WIDGET(dial), NULL);

>               if (dial->policy == GTK_UPDATE_DELAYED)
>                 {
>                   if (dial->timer)
>                     gtk_timeout_remove (dial->timer);

>                   dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
>                                                  (GtkFunction) gtk_dial_timer,
>                                                  (gpointer) dial);
>                 }
>             }
>         }
>     }

>     static void
>     gtk_dial_update (GtkDial *dial)
>     {
>       gfloat new_value;

>       g_return_if_fail (dial != NULL);
>       g_return_if_fail (GTK_IS_DIAL (dial));

>       new_value = dial->adjustment->value;

>       if (new_value < dial->adjustment->lower)
>         new_value = dial->adjustment->lower;

>       if (new_value > dial->adjustment->upper)
>         new_value = dial->adjustment->upper;

>       if (new_value != dial->adjustment->value)
>         {
>           dial->adjustment->value = new_value;
>           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
>         }

>       dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
>         (dial->adjustment->upper - dial->adjustment->lower);

>       gtk_widget_draw (GTK_WIDGET(dial), NULL);
>     }

>     static void
>     gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
>                                   gpointer       data)
>     {
>       GtkDial *dial;

>       g_return_if_fail (adjustment != NULL);
>       g_return_if_fail (data != NULL);

>       dial = GTK_DIAL (data);

>       if ((dial->old_value != adjustment->value) ||
>           (dial->old_lower != adjustment->lower) ||
>           (dial->old_upper != adjustment->upper))
>         {
>           gtk_dial_update (dial);

>           dial->old_value = adjustment->value;
>           dial->old_lower = adjustment->lower;
>           dial->old_upper = adjustment->upper;
>         }
>     }

>     static void
>     gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
>                                         gpointer       data)
>     {
>       GtkDial *dial;

>       g_return_if_fail (adjustment != NULL);
>       g_return_if_fail (data != NULL);

>       dial = GTK_DIAL (data);

>       if (dial->old_value != adjustment->value)
>         {
>           gtk_dial_update (dial);

>           dial->old_value = adjustment->value;
>         }
>     }
>     /* example-end */

> `

### dial_test.c

> `

>     #include <stdio.h>
>     #include <gtk/gtk.h>
>     #include "gtkdial.h"

>     void value_changed( GtkAdjustment *adjustment,
>                         GtkWidget     *label )
>     {
>       char buffer[16];

>       sprintf(buffer,"%4.2f",adjustment->value);
>       gtk_label_set (GTK_LABEL (label), buffer);
>     }

>     int main( int   argc,
>               char *argv[])
>     {
>       GtkWidget *window;
>       GtkAdjustment *adjustment;
>       GtkWidget *dial;
>       GtkWidget *frame;
>       GtkWidget *vbox;
>       GtkWidget *label;

>       gtk_init (&argc, &argv);

>       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

>       gtk_window_set_title (GTK_WINDOW (window), "Dial");

>       gtk_signal_connect (GTK_OBJECT (window), "destroy",
>                           GTK_SIGNAL_FUNC (gtk_exit), NULL);

>       gtk_container_border_width (GTK_CONTAINER (window), 10);

>       vbox = gtk_vbox_new (FALSE, 5);
>       gtk_container_add (GTK_CONTAINER (window), vbox);
>       gtk_widget_show(vbox);

>       frame = gtk_frame_new (NULL);
>       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
>       gtk_container_add (GTK_CONTAINER (vbox), frame);
>       gtk_widget_show (frame);

>       adjustment = GTK_ADJUSTMENT(gtk_adjustment_new (0, 0, 100, 0.01, 0.1, 0));

>       dial = gtk_dial_new(adjustment);
>       gtk_dial_set_update_policy (GTK_DIAL(dial), GTK_UPDATE_DELAYED);
>       /*  gtk_widget_set_usize (dial, 100, 100); */

>       gtk_container_add (GTK_CONTAINER (frame), dial);
>       gtk_widget_show (dial);

>       label = gtk_label_new("0.00");
>       gtk_box_pack_end (GTK_BOX(vbox), label, 0, 0, 0);
>       gtk_widget_show (label);

>       gtk_signal_connect (GTK_OBJECT(adjustment), "value_changed",
>                           GTK_SIGNAL_FUNC (value_changed), label);

>       gtk_widget_show (window);

>       gtk_main ();

>       return 0;
>     }

> `

## 30.3 Scribble

### scribble-simple.c

> `

>     /* example-start scribble-simple scribble-simple.c */

>     /* GTK - The GIMP Toolkit
>      * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
>      *
>      * This library is free software; you can redistribute it and/or
>      * modify it under the terms of the GNU Library General Public
>      * License as published by the Free Software Foundation; either
>      * version 2 of the License, or (at your option) any later version.
>      *
>      * This library 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
>      * Library General Public License for more details.
>      *
>      * You should have received a copy of the GNU Library General Public
>      * License along with this library; if not, write to the
>      * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
>      * Boston, MA 02111-1307, USA.
>      */

>     #include <gtk/gtk.h>

>     /* Backing pixmap for drawing area */
>     static GdkPixmap *pixmap = NULL;

>     /* Create a new backing pixmap of the appropriate size */
>     static gint configure_event( GtkWidget         *widget,
>                                  GdkEventConfigure *event )
>     {
>       if (pixmap)
>         gdk_pixmap_unref(pixmap);

>       pixmap = gdk_pixmap_new(widget->window,
>                               widget->allocation.width,
>                               widget->allocation.height,
>                               -1);
>       gdk_draw_rectangle (pixmap,
>                           widget->style->white_gc,
>                           TRUE,
>                           0, 0,
>                           widget->allocation.width,
>                           widget->allocation.height);

>       return TRUE;
>     }

>     /* Redraw the screen from the backing pixmap */
>     static gint expose_event( GtkWidget      *widget,
>                               GdkEventExpose *event )
>     {
>       gdk_draw_pixmap(widget->window,
>                       widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
>                       pixmap,
>                       event->area.x, event->area.y,
>                       event->area.x, event->area.y,
>                       event->area.width, event->area.height);

>       return FALSE;
>     }

>     /* Draw a rectangle on the screen */
>     static void draw_brush( GtkWidget *widget,
>                             gdouble    x,
>                             gdouble    y)
>     {
>       GdkRectangle update_rect;

>       update_rect.x = x - 5;
>       update_rect.y = y - 5;
>       update_rect.width = 10;
>       update_rect.height = 10;
>       gdk_draw_rectangle (pixmap,
>                           widget->style->black_gc,
>                           TRUE,
>                           update_rect.x, update_rect.y,
>                           update_rect.width, update_rect.height);
>       gtk_widget_draw (widget, &update_rect);
>     }

>     static gint button_press_event( GtkWidget      *widget,
>                                     GdkEventButton *event )
>     {
>       if (event->button == 1 && pixmap != NULL)
>         draw_brush (widget, event->x, event->y);

>       return TRUE;
>     }

>     static gint motion_notify_event( GtkWidget *widget,
>                                      GdkEventMotion *event )
>     {
>       int x, y;
>       GdkModifierType state;

>       if (event->is_hint)
>         gdk_window_get_pointer (event->window, &x, &y, &state);
>       else
>         {
>           x = event->x;
>           y = event->y;
>           state = event->state;
>         }

>       if (state & GDK_BUTTON1_MASK && pixmap != NULL)
>         draw_brush (widget, x, y);

>       return TRUE;
>     }

>     void quit ()
>     {
>       gtk_exit (0);
>     }

>     int main( int   argc,
>               char *argv[] )
>     {
>       GtkWidget *window;
>       GtkWidget *drawing_area;
>       GtkWidget *vbox;

>       GtkWidget *button;

>       gtk_init (&argc, &argv);

>       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
>       gtk_widget_set_name (window, "Test Input");

>       vbox = gtk_vbox_new (FALSE, 0);
>       gtk_container_add (GTK_CONTAINER (window), vbox);
>       gtk_widget_show (vbox);

>       gtk_signal_connect (GTK_OBJECT (window), "destroy",
>                           GTK_SIGNAL_FUNC (quit), NULL);

>       /* Create the drawing area */

>       drawing_area = gtk_drawing_area_new ();
>       gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
>       gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);

>       gtk_widget_show (drawing_area);

>       /* Signals used to handle backing pixmap */

>       gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
>                           (GtkSignalFunc) expose_event, NULL);
>       gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
>                           (GtkSignalFunc) configure_event, NULL);

>       /* Event signals */

>       gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
>                           (GtkSignalFunc) motion_notify_event, NULL);
>       gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
>                           (GtkSignalFunc) button_press_event, NULL);

>       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
>                              | GDK_LEAVE_NOTIFY_MASK
>                              | GDK_BUTTON_PRESS_MASK
>                              | GDK_POINTER_MOTION_MASK
>                              | GDK_POINTER_MOTION_HINT_MASK);

>       /* .. And a quit button */
>       button = gtk_button_new_with_label ("Quit");
>       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);

>       gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
>                                  GTK_SIGNAL_FUNC (gtk_widget_destroy),
>                                  GTK_OBJECT (window));
>       gtk_widget_show (button);

>       gtk_widget_show (window);

>       gtk_main ();

>       return 0;
>     }
>     /* example-end */

> `

### scribble-xinput.c

> `

>     /* example-start scribble-xinput scribble-xinput.c */

>     /* GTK - The GIMP Toolkit
>      * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
>      *
>      * This library is free software; you can redistribute it and/or
>      * modify it under the terms of the GNU Library General Public
>      * License as published by the Free Software Foundation; either
>      * version 2 of the License, or (at your option) any later version.
>      *
>      * This library 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
>      * Library General Public License for more details.
>      *
>      * You should have received a copy of the GNU Library General Public
>      * License along with this library; if not, write to the
>      * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
>      * Boston, MA 02111-1307, USA.
>      */

>     #include <gtk/gtk.h>

>     /* Backing pixmap for drawing area */
>     static GdkPixmap *pixmap = NULL;

>     /* Create a new backing pixmap of the appropriate size */
>     static gint
>     configure_event (GtkWidget *widget, GdkEventConfigure *event)
>     {
>       if (pixmap)
>          gdk_pixmap_unref(pixmap);

>       pixmap = gdk_pixmap_new(widget->window,
>                               widget->allocation.width,
>                               widget->allocation.height,
>                               -1);
>       gdk_draw_rectangle (pixmap,
>                           widget->style->white_gc,
>                           TRUE,
>                           0, 0,
>                           widget->allocation.width,
>                           widget->allocation.height);

>       return TRUE;
>     }

>     /* Redraw the screen from the backing pixmap */
>     static gint
>     expose_event (GtkWidget *widget, GdkEventExpose *event)
>     {
>       gdk_draw_pixmap(widget->window,
>                       widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
>                       pixmap,
>                       event->area.x, event->area.y,
>                       event->area.x, event->area.y,
>                       event->area.width, event->area.height);

>       return FALSE;
>     }

>     /* Draw a rectangle on the screen, size depending on pressure,
>        and color on the type of device */
>     static void
>     draw_brush (GtkWidget *widget, GdkInputSource source,
>                 gdouble x, gdouble y, gdouble pressure)
>     {
>       GdkGC *gc;
>       GdkRectangle update_rect;

>       switch (source)
>         {
>         case GDK_SOURCE_MOUSE:
>           gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
>           break;
>         case GDK_SOURCE_PEN:
>           gc = widget->style->black_gc;
>           break;
>         case GDK_SOURCE_ERASER:
>           gc = widget->style->white_gc;
>           break;
>         default:
>           gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
>         }

>       update_rect.x = x - 10 * pressure;
>       update_rect.y = y - 10 * pressure;
>       update_rect.width = 20 * pressure;
>       update_rect.height = 20 * pressure;
>       gdk_draw_rectangle (pixmap, gc, TRUE,
>                           update_rect.x, update_rect.y,
>                           update_rect.width, update_rect.height);
>       gtk_widget_draw (widget, &update_rect);
>     }

>     static void
>     print_button_press (guint32 deviceid)
>     {
>       GList *tmp_list;

>       /* gdk_input_list_devices returns an internal list, so we shouldn't
>          free it afterwards */
>       tmp_list = gdk_input_list_devices();

>       while (tmp_list)
>         {
>           GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;

>           if (info->deviceid == deviceid)
>             {
>               g_print("Button press on device '%s'\n", info->name);
>               return;
>             }

>           tmp_list = tmp_list->next;
>         }
>     }

>     static gint
>     button_press_event (GtkWidget *widget, GdkEventButton *event)
>     {
>       print_button_press (event->deviceid);

>       if (event->button == 1 && pixmap != NULL)
>         draw_brush (widget, event->source, event->x, event->y, event->pressure);

>       return TRUE;
>     }

>     static gint
>     motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
>     {
>       gdouble x, y;
>       gdouble pressure;
>       GdkModifierType state;

>       if (event->is_hint)
>         gdk_input_window_get_pointer (event->window, event->deviceid,
>                                       &x, &y, &pressure,
>                                       NULL, NULL, &state);
>       else
>         {
>           x = event->x;
>           y = event->y;
>           pressure = event->pressure;
>           state = event->state;
>         }

>       if (state & GDK_BUTTON1_MASK && pixmap != NULL)
>         draw_brush (widget, event->source, x, y, pressure);

>       return TRUE;
>     }

>     void
>     input_dialog_destroy (GtkWidget *w, gpointer data)
>     {
>       *((GtkWidget **)data) = NULL;
>     }

>     void
>     create_input_dialog ()
>     {
>       static GtkWidget *inputd = NULL;

>       if (!inputd)
>         {
>           inputd = gtk_input_dialog_new();

>           gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
>                               (GtkSignalFunc)input_dialog_destroy, &inputd);
>           gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
>                                      "clicked",
>                                      (GtkSignalFunc)gtk_widget_hide,
>                                      GTK_OBJECT(inputd));
>           gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);

>           gtk_widget_show (inputd);
>         }
>       else
>         {
>           if (!GTK_WIDGET_MAPPED(inputd))
>             gtk_widget_show(inputd);
>           else
>             gdk_window_raise(inputd->window);
>         }
>     }

>     void
>     quit ()
>     {
>       gtk_exit (0);
>     }

>     int
>     main (int argc, char *argv[])
>     {
>       GtkWidget *window;
>       GtkWidget *drawing_area;
>       GtkWidget *vbox;

>       GtkWidget *button;

>       gtk_init (&argc, &argv);

>       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
>       gtk_widget_set_name (window, "Test Input");

>       vbox = gtk_vbox_new (FALSE, 0);
>       gtk_container_add (GTK_CONTAINER (window), vbox);
>       gtk_widget_show (vbox);

>       gtk_signal_connect (GTK_OBJECT (window), "destroy",
>                           GTK_SIGNAL_FUNC (quit), NULL);

>       /* Create the drawing area */

>       drawing_area = gtk_drawing_area_new ();
>       gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
>       gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);

>       gtk_widget_show (drawing_area);

>       /* Signals used to handle backing pixmap */

>       gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
>                           (GtkSignalFunc) expose_event, NULL);
>       gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
>                           (GtkSignalFunc) configure_event, NULL);

>       /* Event signals */

>       gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
>                           (GtkSignalFunc) motion_notify_event, NULL);
>       gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
>                           (GtkSignalFunc) button_press_event, NULL);

>       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
>                              | GDK_LEAVE_NOTIFY_MASK
>                              | GDK_BUTTON_PRESS_MASK
>                              | GDK_POINTER_MOTION_MASK
>                              | GDK_POINTER_MOTION_HINT_MASK);

>       /* The following call enables tracking and processing of extension
>          events for the drawing area */
>       gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);

>       /* .. And some buttons */
>       button = gtk_button_new_with_label ("Input Dialog");
>       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);

>       gtk_signal_connect (GTK_OBJECT (button), "clicked",
>                           GTK_SIGNAL_FUNC (create_input_dialog), NULL);
>       gtk_widget_show (button);

>       button = gtk_button_new_with_label ("Quit");
>       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);

>       gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
>                                  GTK_SIGNAL_FUNC (gtk_widget_destroy),
>                                  GTK_OBJECT (window));
>       gtk_widget_show (button);

>       gtk_widget_show (window);

>       gtk_main ();

>       return 0;
>     }
>     /* example-end */

> `

Next Previous Contents