Logo Search packages:      
Sourcecode: libjsw version File versions

jcwidgets.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <gtk/gtk.h>

#include <jsw.h>

#include "guiutils.h"
#include "jc.h"

#include "config.h"
#include "helpmesgs.h"


#include "images/jscalibrator.xpm"
#include "images/icon_calibrate_20x20.xpm"

gint JCCreateRepresentativeLayoutWidgets(
      jc_struct *jc, layout_rep_struct *lr
);
void JCDestroyRepresentativeLayoutWidgets(
      jc_struct *jc, layout_rep_struct *lr
);

gint JCCreateLogicalLayoutWidgets(
        jc_struct *jc, layout_logical_struct *ll,
        GtkWidget *parent       /* Hbox inside notebook. */
);
void JCUpdateLogicalLayoutWidgets(
        jc_struct *jc, layout_logical_struct *ll
);
void JCDestroyLogicalLayoutWidgets(
      jc_struct *jc, layout_logical_struct *ll
);
gint JCCreateButtonsList(jc_struct *jc);
void JCDestroyButtonsList(jc_struct *jc);

void JCUpateDeviceComboList(jc_struct *jc);
GtkWidget *JCCreateMenuBar(jc_struct *jc);
gint JCCreateWidgets(jc_struct *jc, gint argc, gchar **argv);
void JCDestroyWidgets(jc_struct *jc);


/*
 *    Create widgets for the representative layout.
 */
gint JCCreateRepresentativeLayoutWidgets(
      jc_struct *jc, layout_rep_struct *lr
)
{
      gint border_minor = 2;
      gint width, height;
      GdkColormap *colormap;
      GdkPixmap *pixmap;
      GtkWidget *w, *parent, *parent2, *parent3;
        GdkColor *c;


      if((jc == NULL) || (lr == NULL))
          return(-1);

      /* Representative axis layout parent must be valid. */
      if(jc->layout_rep_parent == NULL)
          return(-1);

      /* Get the representative axis layout client parent and create
       * it as needed.
       */
      w = jc->layout_rep_parent_client;
      if(w == NULL)
      {
          jc->layout_rep_parent_client = w = gtk_hbox_new(TRUE, 0);
          gtk_box_pack_start(
            GTK_BOX(jc->layout_rep_parent), w,
            TRUE, TRUE, 0
          );
          gtk_widget_show(w);
      }
      parent = w;

      /* Record client parent on representative layout structure. */
      lr->toplevel = parent;


      /* Get toplevel widget. */
      w = jc->toplevel;

      /* Get colormap and begin creating colors. */
      colormap = jc->colormap;

      c = &lr->c_axis_bg;
        c->red = 0xffff;
        c->green = 0xffff;
        c->blue = 0xffff;
        gdk_colormap_alloc_color(colormap, c, TRUE, TRUE);

      c = &lr->c_axis_fg;
        c->red = 0x0000;
        c->green = 0x0000;
        c->blue = 0x0000;
      gdk_colormap_alloc_color(colormap, c, TRUE, TRUE);

        c = &lr->c_axis_grid;
        c->red = 0x8000;
        c->green = 0x8000;
        c->blue = 0x8000;
      gdk_colormap_alloc_color(colormap, c, TRUE, TRUE);

        c = &lr->c_axis_hat;
        c->red = 0x0000;
        c->green = 0x0000;
        c->blue = 0x0000;
      gdk_colormap_alloc_color(colormap, c, TRUE, TRUE);

      c = &lr->c_throttle_fg;
        c->red = 0xffff;
        c->green = 0x0000;
        c->blue = 0x0000;
      gdk_colormap_alloc_color(colormap, c, TRUE, TRUE);


      /* Begin creating widgets. */

      /* Table to hold label and axis drawing area widgets. */
      w = gtk_table_new(4, 3, FALSE);
      gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
      gtk_widget_show(w);
      parent2 = w;

      /* Instructions label. */
      lr->instructions_label = w = gtk_label_new(
          HELP_MESG_REPRESENTATIVE
      );
      gtk_table_attach(
          GTK_TABLE(parent2), w,
            0, 1,
            0, 4,
            GTK_SHRINK,
            GTK_SHRINK,
            border_minor, border_minor
        );
      gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT);
      gtk_widget_show(w);

      /* Calibrate toggle. */
      lr->calib_toggle = w = GUIToggleButtonPixmapLabelH(
          (u_int8_t **)icon_calibrate_20x20_xpm,
          "Calibrate",
          NULL
      );
        gtk_table_attach(
          GTK_TABLE(parent2), w,
            1, 2,
            0, 1,
            GTK_SHRINK,
            GTK_SHRINK,
          border_minor, border_minor
        );
      gtk_widget_set_usize(
          w,
          JC_DEF_CALIBRATE_TOGGLE_WIDTH, JC_DEF_CALIBRATE_TOGGLE_HEIGHT
      );
      gtk_signal_connect(
          GTK_OBJECT(w), "clicked",
            GTK_SIGNAL_FUNC(JCCalibToggleCB),
            (gpointer)jc
      );
      gtk_signal_connect(
            GTK_OBJECT(w), "enter_notify_event",
            GTK_SIGNAL_FUNC(JCEnterNotifyEventCB),
            (gpointer)jc
        );
        gtk_signal_connect(
            GTK_OBJECT(w), "leave_notify_event",
            GTK_SIGNAL_FUNC(JCLeaveNotifyEventCB),
            (gpointer)jc
        );
        gtk_widget_show(w);  


        /* Hat axises. */
      /* Frame. */
      w = gtk_frame_new(NULL);
      gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_IN);
        gtk_table_attach(
            GTK_TABLE(parent2), w,
            1, 2,
            1, 2,
            GTK_SHRINK,
            GTK_SHRINK,
            2, 2
        );
      gtk_widget_show(w);
      parent3 = w;
      /* Drawing area. */
        width = 50;
        height = 50;
      lr->hat_da = w = gtk_drawing_area_new();
      gtk_widget_set_events(
          w,
          GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
          GDK_BUTTON_RELEASE_MASK
      );
        gtk_signal_connect(
          GTK_OBJECT(w), "expose_event",
            GTK_SIGNAL_FUNC(JCExposeEventCB), (gpointer)jc
        );
        gtk_drawing_area_size(GTK_DRAWING_AREA(w), width, height);
      gtk_container_add(GTK_CONTAINER(parent3), w);
        gtk_widget_show(w);
      /* GdkPixmap drawing buffer. */
      lr->hat_buf = pixmap = gdk_pixmap_new(
            ((jc->toplevel == NULL) ? 0 : jc->toplevel->window),
            width, height, -1
        );


      /* First two (x and y) axises. */
      /* Frame. */
        w = gtk_frame_new(NULL);
        gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_IN);
        gtk_table_attach(
          GTK_TABLE(parent2), w,
            1, 2,
            2, 3,
            GTK_SHRINK,
            GTK_SHRINK,
            border_minor, border_minor
        );
        gtk_widget_show(w);
        parent3 = w;
        /* Drawing area. */
      width = 100;
      height = 100;
      lr->axis_da = w = gtk_drawing_area_new();
        gtk_widget_set_events(
            w,
            GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
            GDK_BUTTON_RELEASE_MASK
      );
        gtk_signal_connect(
          GTK_OBJECT(w), "expose_event",
            GTK_SIGNAL_FUNC(JCExposeEventCB), (gpointer)jc
        );
      gtk_drawing_area_size(GTK_DRAWING_AREA(w), width, height);
        gtk_container_add(GTK_CONTAINER(parent3), w);
        gtk_widget_show(w);
        /* GdkPixmap drawing buffer. */
      lr->axis_buf = pixmap = gdk_pixmap_new(
          ((jc->toplevel == NULL) ? 0 : jc->toplevel->window),
          width, height, -1
      );


        /* Throttle axis. */
        /* Frame. */
        w = gtk_frame_new(NULL);
        gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_IN);
        gtk_table_attach(
          GTK_TABLE(parent2), w,
            2, 3,
            2, 3,
            GTK_SHRINK,
            GTK_SHRINK,
            border_minor, border_minor
        );
        gtk_widget_show(w);
        parent3 = w;
        /* Drawing area. */
        width = 15;
        height = 100;
      lr->throttle_da = w = gtk_drawing_area_new();
        gtk_widget_set_events(
            w,
            GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
            GDK_BUTTON_RELEASE_MASK
      );
        gtk_signal_connect(
          GTK_OBJECT(w), "expose_event",
            GTK_SIGNAL_FUNC(JCExposeEventCB), (gpointer)jc
        );
        gtk_drawing_area_size(GTK_DRAWING_AREA(w), width, height);
        gtk_container_add(GTK_CONTAINER(parent3), w);
        gtk_widget_show(w);   
        /* GdkPixmap drawing buffer. */
      lr->throttle_buf = pixmap = gdk_pixmap_new(
            ((jc->toplevel == NULL) ? 0 : jc->toplevel->window),
            width, height, -1
        );


      /* Rotate axis. */
        /* Frame. */
        w = gtk_frame_new(NULL);
        gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_IN);
        gtk_table_attach(
          GTK_TABLE(parent2), w,
            1, 2,
            3, 4,
            GTK_SHRINK,
            GTK_SHRINK,
            border_minor, border_minor
        );
        gtk_widget_show(w);
        parent3 = w;
        /* Drawing area. */
        width = 100;
        height = 15;
      lr->rotate_da = w = gtk_drawing_area_new();
        gtk_widget_set_events(
          w,
          GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
          GDK_BUTTON_RELEASE_MASK
      );
      gtk_signal_connect(
          GTK_OBJECT(w), "expose_event",
          GTK_SIGNAL_FUNC(JCExposeEventCB), (gpointer)jc
      );
        gtk_drawing_area_size(GTK_DRAWING_AREA(w), width, height);
        gtk_container_add(GTK_CONTAINER(parent3), w);
      gtk_widget_show(w);
        /* GdkPixmap drawing buffer. */
        lr->rotate_buf = pixmap = gdk_pixmap_new(
            ((jc->toplevel == NULL) ? 0 : jc->toplevel->window),
            width, height, -1
        );


      return(0);
}

/*
 *    Destroys all widgets and deallocates all resources for the given
 *    representative layout structure but not the structure itself.
 *
 *    Structure will be reset.
 */
void JCDestroyRepresentativeLayoutWidgets(
      jc_struct *jc, layout_rep_struct *lr
)
{
      GdkColor *c;
      GdkColormap *colormap;
      GdkPixmap **pixmap_ptr;
      GtkWidget **widget_ptr;


      if((jc == NULL) || (lr == NULL))
          return;

      colormap = jc->colormap;

      /* Unref pixmaps. */
#define DO_UNREF_PIXMAP \
{ \
 if((*pixmap_ptr) != NULL) \
 { \
  gdk_pixmap_unref(*pixmap_ptr); \
  (*pixmap_ptr) = NULL; \
 } \
}
      pixmap_ptr = &lr->rotate_buf;
      DO_UNREF_PIXMAP

        pixmap_ptr = &lr->throttle_buf;
      DO_UNREF_PIXMAP

      pixmap_ptr = &lr->axis_buf;
      DO_UNREF_PIXMAP

      pixmap_ptr = &lr->hat_buf;
      DO_UNREF_PIXMAP

      /* Destroy widgets. */
#define DO_DESTROY_WIDGET     \
{ \
 if((*widget_ptr) != NULL) \
 { \
  gtk_widget_destroy(*widget_ptr); \
  (*widget_ptr) = NULL; \
 } \
}
      widget_ptr = &lr->axis_da;
      DO_DESTROY_WIDGET

        widget_ptr = &lr->throttle_da;
        DO_DESTROY_WIDGET

        widget_ptr = &lr->rotate_da;
        DO_DESTROY_WIDGET

        widget_ptr = &lr->hat_da;
        DO_DESTROY_WIDGET

        widget_ptr = &lr->calib_toggle;
        DO_DESTROY_WIDGET

      widget_ptr = &lr->instructions_label;
      DO_DESTROY_WIDGET

      /* Free colors. */
#define DO_FREE_COLOR   \
{ \
 if(c != NULL) \
 { \
  gdk_colormap_free_colors(colormap, c, 1); \
  memset(c, 0x00, sizeof(GdkColor)); \
 } \
}
      c = &lr->c_axis_bg;
      DO_FREE_COLOR
      c = &lr->c_axis_fg;
      DO_FREE_COLOR
      c = &lr->c_axis_grid;
      DO_FREE_COLOR
      c = &lr->c_axis_hat;
      DO_FREE_COLOR
      c = &lr->c_throttle_fg;
      DO_FREE_COLOR

      /* Destroy the representative layout client parent GtkVBox incase
       * any child widgets are still left.
       */
      widget_ptr = &jc->layout_rep_parent_client;
      DO_DESTROY_WIDGET

#undef DO_UNREF_PIXMAP
#undef DO_DESTROY_WIDGET
#undef DO_FREE_COLOR

      /* Reset structure. */
      memset(lr, 0x00, sizeof(layout_rep_struct));
}


/*
 *    Create widgets for logical layout.
 */
gint JCCreateLogicalLayoutWidgets(
      jc_struct *jc, layout_logical_struct *ll,
      GtkWidget *parent /* Hbox inside notebook. */
)
{
        GtkWidget *w, *parent2, *parent3;
      GtkObject *adj;
        GdkColor *c;
      GdkColormap *colormap;


        if((jc == NULL) || (ll == NULL) || (parent == NULL))
            return(-1);

      /* Get colormap. */
      colormap = jc->colormap;

      /* Record values on layout logical structure. */
        ll->toplevel = parent;

      ll->axis = NULL;
      ll->total_axises = 0;


      /* Create each axis layout widget group. */
      ll->total_axises = jc->jsd.total_axises;
      if(ll->total_axises > 0)
      {
          gint i, width, height;
          layout_logical_axis_struct *ll_axis_ptr;
          js_axis_struct *axis_ptr;
          gchar text[256];


          /* Allocate pointers to axis layout structures. */
          ll->axis = (layout_logical_axis_struct **)g_malloc0(
              ll->total_axises * sizeof(layout_logical_axis_struct *)
          );
          if(ll->axis == NULL)
          {
              ll->total_axises = 0;
              return(-1);
          }

          /* Allocate and create each new logical layout axis widget. */
          for(i = 0; i < ll->total_axises; i++)
          {
            /* Allocate a new structure. */
            ll_axis_ptr = (layout_logical_axis_struct *)g_malloc0(
                sizeof(layout_logical_axis_struct)
            );
            if(ll_axis_ptr == NULL)
                continue;

            ll->axis[i] = ll_axis_ptr;

            /* Get pointer to axis on joystick data. */
            if(JSIsAxisAllocated(&jc->jsd, i))
                axis_ptr = jc->jsd.axis[i];
            else
                axis_ptr = NULL;


            /* Begin creating widgets, marking ll_axis_ptr as not
             * initialized so callbacks know its not done 
             * intiializing.
             */
            ll_axis_ptr->initialized = FALSE;

                /* Colors. */
                w = jc->toplevel;
                c = &ll_axis_ptr->c_axis_bg; 
                c->red = (guint16)(1.0 * (guint16)-1);
                c->green = (guint16)(1.0 * (guint16)-1);
            c->blue = (guint16)(1.0 * (guint16)-1);
            gdk_colormap_alloc_color(colormap, c, TRUE, TRUE);

                c = &ll_axis_ptr->c_axis_fg;
                c->red = (guint16)(0.0 * (guint16)-1);
                c->green = (guint16)(0.0 * (guint16)-1);
                c->blue = (guint16)(0.0 * (guint16)-1);
            gdk_colormap_alloc_color(colormap, c, TRUE, TRUE);

                c = &ll_axis_ptr->c_axis_grid;
                c->red = (guint16)(0.5 * (guint16)-1);
                c->green = (guint16)(0.5 * (guint16)-1);
                c->blue = (guint16)(0.5 * (guint16)-1);
            gdk_colormap_alloc_color(colormap, c, TRUE, TRUE);

                c = &ll_axis_ptr->c_axis_nz;
                c->red = (guint16)(0.75 * (guint16)-1);
                c->green = (guint16)(0.75 * (guint16)-1);
                c->blue = (guint16)(0.75 * (guint16)-1);
                gdk_colormap_alloc_color(colormap, c, TRUE, TRUE);

            /* Font. */
            ll_axis_ptr->font = gdk_font_load(
"-adobe-helvetica-medium-r-normal-*-10-*-*-*-*-*-iso8859-1"
            );
            if(ll_axis_ptr->font == NULL)
                ll_axis_ptr->font = gdk_font_load(
"-*-fixed-*-*-*-*-10-*-*-*-*-*-*-*"
                );

            /* Main hbox (toplevel), parent for this axis's widgets. */
            ll_axis_ptr->toplevel = w = gtk_hbox_new(FALSE, 2);
            gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
            gtk_widget_show(w);
            parent2 = w;


            /* Axis number label. */
            sprintf(text, "Axis %i:", i);
            ll_axis_ptr->axis_num_label = w = gtk_label_new(text);
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
                gtk_widget_show(w);


            /* Vbox for axis gauge, to align it centered. */
            w = gtk_vbox_new(TRUE, 0);
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
            gtk_widget_show(w);
            parent3 = w;
            /* Frame. */
            w = gtk_frame_new(NULL);
            gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_IN);
            gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, FALSE, 0);
                gtk_widget_show(w);
                parent3 = w;
            /* Drawing area. */
            width = 100;
            height = 18;
            ll_axis_ptr->position_da = w = gtk_drawing_area_new();
                gtk_widget_set_events(
                w,
                GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
                GDK_BUTTON_RELEASE_MASK
            );
            gtk_signal_connect(
                GTK_OBJECT(w), "expose_event",
                GTK_SIGNAL_FUNC(JCExposeEventCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "button_press_event",
                    GTK_SIGNAL_FUNC(JCButtonPressEventCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "button_release_event",
                    GTK_SIGNAL_FUNC(JCButtonReleaseEventCB), (gpointer)jc
                );
                gtk_drawing_area_size(GTK_DRAWING_AREA(w), width, height);
            gtk_container_add(GTK_CONTAINER(parent3), w);
            gtk_widget_show(w);
            /* GdkPixmap buffer. */
            ll_axis_ptr->position_buf = gdk_pixmap_new(
                ((jc->toplevel == NULL) ? 0 : jc->toplevel->window),
                width, height, -1
            );


            /* Calibrate toggle. */
            ll_axis_ptr->calib_toggle = w = GUIToggleButtonPixmap(
                (u_int8_t **)icon_calibrate_20x20_xpm
            );
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
            gtk_signal_connect(
                GTK_OBJECT(w), "clicked",
                GTK_SIGNAL_FUNC(JCCalibToggleCB), (gpointer)jc
            );
                gtk_signal_connect(
                    GTK_OBJECT(w), "enter_notify_event",
                    GTK_SIGNAL_FUNC(JCEnterNotifyEventCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "leave_notify_event",
                    GTK_SIGNAL_FUNC(JCLeaveNotifyEventCB), (gpointer)jc
                );
            gtk_widget_show(w);


            /* Null zone spin. */
                w = gtk_label_new("NZ:");
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
                gtk_widget_show(w);

            ll_axis_ptr->nz_adj = adj = gtk_adjustment_new(
                (axis_ptr != NULL) ? axis_ptr->nz : 0.0,
                0.0,
                1000000.0,    /* One million should be a good upper bound. */
                1.0, 5.0, 1.0 /* Step inc, page inc, and page size. */
            );
            gtk_object_ref(adj);    /* Keep a refcount for ourself. */
            ll_axis_ptr->nz_spin = w = gtk_spin_button_new(
                (GtkAdjustment *)adj,
                1.0,          /* Climb rate (acceleration). */
                0             /* Must be whole numbers. */
            );
            gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(w), FALSE);
            gtk_widget_set_usize(w, 55, -1);
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
            gtk_signal_connect(
                GTK_OBJECT(w), "changed",
                GTK_SIGNAL_FUNC(JCEditableChangedCB), (gpointer)jc
            );
            gtk_signal_connect(
                GTK_OBJECT(w), "enter_notify_event",
                GTK_SIGNAL_FUNC(JCEnterNotifyEventCB), (gpointer)jc
            );
            gtk_signal_connect(
                GTK_OBJECT(w), "leave_notify_event",
                GTK_SIGNAL_FUNC(JCLeaveNotifyEventCB), (gpointer)jc
            );
                gtk_widget_show(w);


            /* Correction level spin. */
                w = gtk_label_new("CL:");
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
                gtk_widget_show(w);

                ll_axis_ptr->correction_level_adj = adj = gtk_adjustment_new(
                    (axis_ptr != NULL) ? axis_ptr->correction_level : 0.0,
                    0.0,
                    100.0,    /* One hundred should be a good upper bound. */
                    1.0, 1.0, 1.0       /* Step inc, page inc, and page size. */
                );
                gtk_object_ref(adj);    /* Keep a refcount for ourself. */
                ll_axis_ptr->correction_level_spin = w = gtk_spin_button_new(
                    (GtkAdjustment *)adj,
                    1.0,                /* Climb rate (acceleration). */
                    0                   /* Must be whole numbers. */
                );
                gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(w), FALSE);
                gtk_widget_set_usize(w, 40, -1);
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
                gtk_signal_connect(
                    GTK_OBJECT(w), "changed",
                    GTK_SIGNAL_FUNC(JCEditableChangedCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "enter_notify_event",
                    GTK_SIGNAL_FUNC(JCEnterNotifyEventCB),
                    (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "leave_notify_event",
                    GTK_SIGNAL_FUNC(JCLeaveNotifyEventCB),
                    (gpointer)jc
                );
                gtk_widget_show(w);


                /* Dead zone min and max spins. */
                w = gtk_label_new("DZ:");
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
                gtk_widget_show(w);

                ll_axis_ptr->dz_min_adj = adj = gtk_adjustment_new(
                    (axis_ptr != NULL) ? axis_ptr->dz_min : 0.0,
                -1000000.0, 10000000.0,   /* Big bounds. */
                    1.0, 10.0, 1.0  /* Step inc, page inc, and page size. */
                );
                gtk_object_ref(adj);    /* Keep a refcount for ourself. */
                ll_axis_ptr->dz_min_spin = w = gtk_spin_button_new(
                    (GtkAdjustment *)adj,
                    1.0,                /* Climb rate (acceleration). */
                    0                   /* Must be whole numbers. */
                );
                gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(w), FALSE);
                gtk_widget_set_usize(w, 55, -1);
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
                gtk_signal_connect(
                    GTK_OBJECT(w), "changed",
                    GTK_SIGNAL_FUNC(JCEditableChangedCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "enter_notify_event",
                    GTK_SIGNAL_FUNC(JCEnterNotifyEventCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "leave_notify_event",
                    GTK_SIGNAL_FUNC(JCLeaveNotifyEventCB), (gpointer)jc
                );
                gtk_widget_show(w);

                ll_axis_ptr->dz_max_adj = adj = gtk_adjustment_new(
                    (axis_ptr != NULL) ? axis_ptr->dz_max : 0.0,
                    -1000000.0, 10000000.0,     /* Big bounds. */
                    1.0, 10.0, 1.0      /* Step inc, page inc, and page size. */
                );
                gtk_object_ref(adj);    /* Keep a refcount for ourself. */
                ll_axis_ptr->dz_max_spin = w = gtk_spin_button_new(
                    (GtkAdjustment *)adj,
                    1.0,                /* Climb rate (acceleration). */
                    0                   /* Must be whole numbers. */
                );
                gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(w), FALSE);
                gtk_widget_set_usize(w, 55, -1);
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
                gtk_signal_connect(
                    GTK_OBJECT(w), "changed",
                    GTK_SIGNAL_FUNC(JCEditableChangedCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "enter_notify_event",
                    GTK_SIGNAL_FUNC(JCEnterNotifyEventCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "leave_notify_event",
                    GTK_SIGNAL_FUNC(JCLeaveNotifyEventCB), (gpointer)jc
                );
                gtk_widget_show(w);


                /* Correctional coefficient min and max spins. */
                w = gtk_label_new("CC1:");
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
                gtk_widget_show(w);

                ll_axis_ptr->corr_coeff_min1_adj = adj = gtk_adjustment_new(
                    (axis_ptr != NULL) ? axis_ptr->corr_coeff_min1 : 0.0,
                    0.0, 1.0,
                    0.01, 0.05, 0.01      /* Step inc, page inc, and page size. */
                );
                gtk_object_ref(adj);    /* Keep a refcount for ourself. */
                ll_axis_ptr->corr_coeff_min1_spin = w = gtk_spin_button_new(
                    (GtkAdjustment *)adj,
                    1.0,                /* Climb rate (acceleration). */
                    2                   /* Two decimals. */
                );
                gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(w), FALSE);
                gtk_widget_set_usize(w, 45, -1);
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
                gtk_signal_connect(
                    GTK_OBJECT(w), "changed",
                    GTK_SIGNAL_FUNC(JCEditableChangedCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "enter_notify_event",
                    GTK_SIGNAL_FUNC(JCEnterNotifyEventCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "leave_notify_event",
                    GTK_SIGNAL_FUNC(JCLeaveNotifyEventCB), (gpointer)jc
                );
                gtk_widget_show(w);

                ll_axis_ptr->corr_coeff_max1_adj = adj = gtk_adjustment_new(
                    (axis_ptr != NULL) ? axis_ptr->corr_coeff_max1 : 0.0,
                    0.0, 1.0,
                    0.01, 0.05, 0.01    /* Step inc, page inc, and page size. */
                );
                gtk_object_ref(adj);    /* Keep a refcount for ourself. */
                ll_axis_ptr->corr_coeff_max1_spin = w = gtk_spin_button_new(
                    (GtkAdjustment *)adj,
                    1.0,                /* Climb rate (acceleration). */
                    2                   /* Two decimals. */
                );
                gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(w), FALSE);
                gtk_widget_set_usize(w, 45, -1);
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
                gtk_signal_connect(
                    GTK_OBJECT(w), "changed",
                    GTK_SIGNAL_FUNC(JCEditableChangedCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "enter_notify_event",
                    GTK_SIGNAL_FUNC(JCEnterNotifyEventCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "leave_notify_event",
                    GTK_SIGNAL_FUNC(JCLeaveNotifyEventCB), (gpointer)jc
                );
                gtk_widget_show(w);


                /* Flip axis values check. */
                ll_axis_ptr->flipped_check = w = gtk_check_button_new_with_label(
                    "Flip"
                );
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
                if(axis_ptr != NULL)
                    gtk_toggle_button_set_active(
                        GTK_TOGGLE_BUTTON(w),
                        (axis_ptr->flags & JSAxisFlagFlipped) ? TRUE : FALSE
                    );
                gtk_signal_connect(
                    GTK_OBJECT(w), "clicked",
                    GTK_SIGNAL_FUNC(JCCalibFlipCheckCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "enter_notify_event",
                    GTK_SIGNAL_FUNC(JCEnterNotifyEventCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "leave_notify_event",
                    GTK_SIGNAL_FUNC(JCLeaveNotifyEventCB), (gpointer)jc
                );
                gtk_widget_show(w);


                /* Is hat check. */
                ll_axis_ptr->is_hat_check = w = gtk_check_button_new_with_label(
                    "Hat"
                );
                gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
                if(axis_ptr != NULL)
                    gtk_toggle_button_set_active(
                        GTK_TOGGLE_BUTTON(w),
                        (axis_ptr->flags & JSAxisFlagIsHat) ? TRUE : FALSE
                    );
                gtk_signal_connect(
                    GTK_OBJECT(w), "clicked",
                    GTK_SIGNAL_FUNC(JCCalibIsHatCheckCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "enter_notify_event",
                    GTK_SIGNAL_FUNC(JCEnterNotifyEventCB), (gpointer)jc
                );
                gtk_signal_connect(
                    GTK_OBJECT(w), "leave_notify_event",
                    GTK_SIGNAL_FUNC(JCLeaveNotifyEventCB), (gpointer)jc
                );
                gtk_widget_show(w);


            /* Mark axis as initialized after all callbacks have been set. */
            ll_axis_ptr->initialized = TRUE;

          } /* for(i = 0; i < ll->total_axises; i++) */
      }


      return(0);
}

/*
 *    Updates all logical axis layout widgets in the given structure
 *    to fetch new values from the currently opened joystick device.
 */
void JCLogicalLayoutWidgetsGetValues(
        jc_struct *jc, layout_logical_struct *ll
)
{
        gint i;
        layout_logical_axis_struct *ll_axis_ptr;
      GtkWidget *w;
        js_axis_struct *axis_ptr;


        if((jc == NULL) || (ll == NULL))
            return;

      /* Itterate through each axis on the logical axis layout
       * structure and update each axis with values from the jsd
       * structure's axises.
       */
        for(i = 0; i < ll->total_axises; i++)
        {
            ll_axis_ptr = ll->axis[i];
            if(ll_axis_ptr == NULL)
                continue;

          /* Skip if not initialized. */
            if(!ll_axis_ptr->initialized)
                continue;

            /* Get pointer to axis on joystick data. */
            if(JSIsAxisAllocated(&jc->jsd, i))
                axis_ptr = jc->jsd.axis[i];
            else
            continue;

          /* Begin getting values from axis structure and storing them
           * on the widgets.
           */

          /* Null zone spin. */
          w = ll_axis_ptr->nz_spin;
          if(w != NULL)
            gtk_spin_button_set_value(
                GTK_SPIN_BUTTON(w),
                (gfloat)axis_ptr->nz
            );

          /* Is hat check. */
          w = ll_axis_ptr->is_hat_check;
          if(w != NULL)
                gtk_toggle_button_set_active(
                    GTK_TOGGLE_BUTTON(w),
                    (axis_ptr->flags & JSAxisFlagIsHat) ? TRUE : FALSE
                );

            /* Flip axis check. */
          w = ll_axis_ptr->flipped_check;
          if(w != NULL)
                gtk_toggle_button_set_active(
                    GTK_TOGGLE_BUTTON(w),
                    (axis_ptr->flags & JSAxisFlagFlipped) ? TRUE : FALSE
                ); 

            /* Error correction level spin. */
            w = ll_axis_ptr->correction_level_spin;
            if(w != NULL)
                gtk_spin_button_set_value(
                    GTK_SPIN_BUTTON(w),
                    (gfloat)axis_ptr->correction_level
            );

            /* Dead zone min spin. */
            w = ll_axis_ptr->dz_min_spin;
            if(w != NULL)
                gtk_spin_button_set_value(
                    GTK_SPIN_BUTTON(w),
                    (gfloat)axis_ptr->dz_min
                );

            /* Dead zone max spin. */
            w = ll_axis_ptr->dz_max_spin;
            if(w != NULL)
                gtk_spin_button_set_value(
                    GTK_SPIN_BUTTON(w),
                    (gfloat)axis_ptr->dz_max
                );

            /* Correctional coefficient min 1 spin. */
            w = ll_axis_ptr->corr_coeff_min1_spin;
            if(w != NULL)
                gtk_spin_button_set_value(
                    GTK_SPIN_BUTTON(w),
                    (gfloat)axis_ptr->corr_coeff_min1
                );

            /* Correctional coefficient max 1 spin. */
            w = ll_axis_ptr->corr_coeff_max1_spin;
            if(w != NULL)
                gtk_spin_button_set_value(
                    GTK_SPIN_BUTTON(w),
                    (gfloat)axis_ptr->corr_coeff_max1
                );

      }
}

/*
 *      Destroys all widgets and resources on the given axis logical
 *    layout structure.
 */
void JCDestroyLogicalLayoutWidgets(
      jc_struct *jc, layout_logical_struct *ll
)
{
      gint i;
      layout_logical_axis_struct *ll_axis_ptr;
      GdkColor *c;
      GdkColormap *colormap;
      GdkFont **font;
      GtkObject **adj;
      GdkPixmap **pixmap_ptr;
      GtkWidget **widget_ptr;


        if((jc == NULL) || (ll == NULL))
            return;

      /* Get colormap. */
      colormap = jc->colormap;

#define DO_FREE_COLOR   \
{ \
 if(c != NULL) \
 { \
  gdk_colormap_free_colors(colormap, c, 1); \
  memset(c, 0x00, sizeof(GdkColor)); \
 } \
}
#define DO_UNREF_ADJ    \
{ \
 if((*adj) != NULL) \
 { \
  GtkObject *tobj = *adj; \
  (*adj) = NULL; \
  gtk_object_unref(tobj); \
 } \
}
#define DO_UNREF_FONT   \
{ \
 if((*font) != NULL) \
 { \
  GdkFont *tf = *font; \
  (*font) = NULL; \
  gdk_font_unref(tf); \
 } \
}
#define DO_UNREF_PIXMAP \
{ \
 if((*pixmap_ptr) != NULL) \
 { \
  gdk_pixmap_unref(*pixmap_ptr); \
  (*pixmap_ptr) = NULL; \
 } \
}
#define DO_DESTROY_WIDGET       \
{ \
 if((*widget_ptr) != NULL) \
 { \
  gtk_widget_destroy(*widget_ptr); \
  (*widget_ptr) = NULL; \
 } \
}

      /* Deallocate each logical layout axis structure. */
      for(i = 0; i < ll->total_axises; i++)
      {
          ll_axis_ptr = ll->axis[i];
          if(ll_axis_ptr == NULL)
            continue;

          pixmap_ptr = &ll_axis_ptr->position_buf;
          DO_UNREF_PIXMAP

            widget_ptr = &ll_axis_ptr->axis_num_label;
            DO_DESTROY_WIDGET

            widget_ptr = &ll_axis_ptr->position_da;
            DO_DESTROY_WIDGET

            widget_ptr = &ll_axis_ptr->calib_toggle;
            DO_DESTROY_WIDGET

            widget_ptr = &ll_axis_ptr->nz_spin;
            DO_DESTROY_WIDGET

            widget_ptr = &ll_axis_ptr->is_hat_check;
            DO_DESTROY_WIDGET

            widget_ptr = &ll_axis_ptr->flipped_check;
            DO_DESTROY_WIDGET

          widget_ptr = &ll_axis_ptr->correction_level_spin;
            DO_DESTROY_WIDGET

            widget_ptr = &ll_axis_ptr->dz_min_spin;
            DO_DESTROY_WIDGET

            widget_ptr = &ll_axis_ptr->dz_max_spin;
            DO_DESTROY_WIDGET

            widget_ptr = &ll_axis_ptr->corr_coeff_min1_spin;
            DO_DESTROY_WIDGET

            widget_ptr = &ll_axis_ptr->corr_coeff_max1_spin;
            DO_DESTROY_WIDGET

          widget_ptr = &ll_axis_ptr->toplevel;
          DO_DESTROY_WIDGET

          font = &ll_axis_ptr->font;
          DO_UNREF_FONT

          c = &ll_axis_ptr->c_axis_bg;
          DO_FREE_COLOR
            c = &ll_axis_ptr->c_axis_fg;
            DO_FREE_COLOR
            c = &ll_axis_ptr->c_axis_grid;
            DO_FREE_COLOR
            c = &ll_axis_ptr->c_axis_nz;
            DO_FREE_COLOR

          adj = &ll_axis_ptr->nz_adj;
          DO_UNREF_ADJ
          adj = &ll_axis_ptr->correction_level_adj;
          DO_UNREF_ADJ
            adj = &ll_axis_ptr->dz_min_adj;
            DO_UNREF_ADJ
            adj = &ll_axis_ptr->dz_max_adj;
            DO_UNREF_ADJ
            adj = &ll_axis_ptr->corr_coeff_min1_adj;
            DO_UNREF_ADJ
            adj = &ll_axis_ptr->corr_coeff_max1_adj;
            DO_UNREF_ADJ

          /* Deallocate axis structure itself. */
          g_free(ll_axis_ptr);
          ll->axis[i] = ll_axis_ptr = NULL;
      }
      g_free(ll->axis);
      ll->axis = NULL;
      ll->total_axises = 0;

#undef DO_UNREF_PIXMAP
#undef DO_DESTROY_WIDGET
#undef DO_UNREF_FONT
#undef DO_UNREF_ADJ
#undef DO_FREE_COLOR

        /* Reset structure. */
        memset(ll, 0x00, sizeof(layout_logical_struct));
}


/*
 *    Creates buttons list for the given jc.
 */
gint JCCreateButtonsList(jc_struct *jc)
{
      gint i, n, total;
      buttons_list_struct *bl;
      GtkWidget *w, *parent;
      gchar text[256];


        if(jc == NULL)
            return(-1);

        bl = &jc->buttons_list;
      if(bl == NULL)
          return(-1);

      /* Get parent vbox. */
      parent = jc->buttons_list_parent;
      bl->toplevel = parent;

      bl->button = NULL;
      bl->total_buttons = 0;

      total = jc->jsd.total_buttons;

      /* Create each button. */
      for(i = 0; i < total; i++)
      {
          /* Allocate a new pointer on the buttons list. */
          n = bl->total_buttons;
          bl->total_buttons++;
          bl->button = (GtkWidget **)g_realloc(
            bl->button,
            bl->total_buttons * sizeof(GtkWidget *)
          );
          if(bl->button == NULL)
          {
            bl->total_buttons = 0;
            break;
          }
          else
          {
            /* Create a new button. */
            sprintf(text, "Button %i", i);
            bl->button[n] = w = gtk_button_new_with_label(text);
            gtk_button_released(GTK_BUTTON(w));
            gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
            gtk_widget_set_usize(
                w,
                JC_DEF_JS_BUTTON_WIDTH, JC_DEF_JS_BUTTON_HEIGHT
            );
            gtk_widget_show(w);
          }
      }


      return(0);
}

/*
 *    Destroys all widgets for the buttons list.
 */
void JCDestroyButtonsList(jc_struct *jc)
{
      gint i;
      buttons_list_struct *bl;
      GtkWidget *w;


      if(jc == NULL)
          return;

      /* Get buttons list. */
      bl = &jc->buttons_list;

      /* Itterate through each button on the buttons list. */
      for(i = 0; i < bl->total_buttons; i++)
      {
          w = bl->button[i];
          if(w == NULL)
            continue;

          gtk_widget_destroy(w);
          bl->button[i] = w = NULL;
      }

      g_free(bl->button);
      bl->button = NULL;
      bl->total_buttons = 0;
}


/*
 *    Updates the joystick device combo list.
 */
void JCUpateDeviceComboList(jc_struct *jc)
{
      GtkCombo *combo;
      GList *glist;


      if(jc == NULL)
          return;

      combo = (GtkCombo *)jc->js_device_combo;
      if(combo == NULL)
          return;

      /* Begin creating new glist. */
      glist = NULL;
      if(1)
      {
          const gchar *cstrptr;
          gint i, total_jsas;
            js_attribute_struct *jsa, *jsa_ptr;


          /* Get attributes of all joysticks on system, note that
           * we pass the calibration file path as NULL since
           * we don't need details from calibration file.
           */
          jsa = JSGetAttributesList(&total_jsas, NULL);

          for(i = 0; i < total_jsas; i++)
          {
            jsa_ptr = &jsa[i];

            /* We're just interested in the device names. */
            cstrptr = jsa_ptr->device_name;
            if(cstrptr != NULL)
            {
                /* Add this device to the list. */
                glist = g_list_append(
                  glist, g_strdup(cstrptr)
                );
            }
          }

          /* Free the list of loaded joystick attributes. */
          JSFreeAttributesList(jsa, total_jsas);
      }

      /* Set new glist to the combo widget's list, we must not
       * referance the passed glist afterwards. The old glist on the
       * combo will be deallocated.
       */
      GUIComboSetList(combo, glist);
      glist = NULL;
}

/*
 *    Procedure to create menu bar widget to the given jc.
 */
GtkWidget *JCCreateMenuBar(jc_struct *jc)
{
      static GtkItemFactoryEntry menu_items[] = {

{ "/_Calibration",          NULL,         NULL,     JC_CMD_NONE, "<Branch>" },
{ "/Calibration/_Open",     "<control>O", JCMenuCB, JC_CMD_OPEN_CALIB, NULL },
{ "/Calibration/sep1",      NULL,         NULL,     JC_CMD_NONE, "<Separator>" },
{ "/Calibration/_Save",     "<control>S", JCMenuCB, JC_CMD_SAVE_CALIB, NULL },
{ "/Calibration/Save _As",  "<control>A", JCMenuCB, JC_CMD_SAVEAS_CALIB, NULL },
{ "/Calibration/sep2",      NULL,         NULL,     JC_CMD_NONE, "<Separator>" },
{ "/Calibration/Clean Up",  NULL,         JCMenuCB, JC_CMD_CLEANUP_CALIB, NULL },
{ "/Calibration/sep3",      NULL,         NULL,     JC_CMD_NONE, "<Separator>" },
{ "/Calibration/E_xit",     "<control>X", JCMenuCB, JC_CMD_EXIT, NULL },
{ "/_Joystick",             NULL,         NULL,     JC_CMD_NONE, "<Branch>" },
{ "/Joystick/_Refresh",     "<control>R", JCMenuCB, JC_CMD_REFRESH, NULL },
{ "/Joystick/sep1",         NULL,         NULL,     JC_CMD_NONE, "<Separator>" },
{ "/Joystick/R_eopen",      "<control>E", JCMenuCB, JC_CMD_REOPEN_DEVICE, NULL },
{ "/Joystick/_Close",       "<control>C", JCMenuCB, JC_CMD_CLOSE_DEVICE, NULL },
{ "/Joystick/sep2",         NULL,         NULL,     JC_CMD_NONE, "<Separator>" },
{ "/Joystick/Properties...", NULL,        JCMenuCB, JC_CMD_JOYSTICK_PROPERTIES, NULL },
{ "/_View",                 NULL,         NULL,     JC_CMD_NONE, "<Branch>" },
{ "/View/Re_presentative",  "<control>P", JCMenuCB, JC_CMD_LAYOUT_REPRESENTATIVE, NULL },
{ "/View/_Logical",         "<control>L", JCMenuCB, JC_CMD_LAYOUT_LOGICAL, NULL },
{ "/_Help",                 NULL,         NULL,     JC_CMD_NONE, "<LastBranch>" },
{ "/Help/Index",            NULL,         JCMenuCB, JC_CMD_HELP_INDEX, NULL },
{ "/Help/sep1",             NULL,         NULL,     JC_CMD_NONE, "<Separator>" },
{ "/Help/Introduction",     NULL,         JCMenuCB, JC_CMD_HELP_INTRODUCTION, NULL },
{ "/Help/How To Calibrate", NULL,         JCMenuCB, JC_CMD_HELP_HOW_TO_CALIBRATE, NULL },
{ "/Help/sep2",             NULL,         NULL,     JC_CMD_NONE, "<Separator>" },
{ "/Help/About",            NULL,         JCMenuCB, JC_CMD_HELP_ABOUT, NULL }

      };

        GtkWidget *menubar;
        GtkItemFactory *item_factory;
        GtkAccelGroup *accel_group;
        gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);


      if(jc == NULL)
          return(NULL);


        accel_group = gtk_accel_group_new();

        /* This function initializes the item factory.
         * Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
         *          or GTK_TYPE_OPTION_MENU.
         * Param 2: The path of the menu.
         * Param 3: A pointer to a gtk_accel_group.  The item factory sets up
         *          the accelerator table while generating menus.
         */
        item_factory = gtk_item_factory_new(
            GTK_TYPE_MENU_BAR,
            "<main>", accel_group
        );

        /* This function generates the menu items. Pass the item factory,
         * the number of items in the array, the array itself, and any
         * callback data for the the menu items.
         */
        gtk_item_factory_create_items(
            item_factory,
            nmenu_items, menu_items,
            jc                      /* Callback data. */
        );

        /* Attach the new accelerator group to the window. */
        gtk_accel_group_attach(accel_group, GTK_OBJECT(jc->toplevel));

      /* Create the menu bar widget using the item factory. */
        menubar = gtk_item_factory_get_widget(item_factory, "<main>");

      return(menubar);
}

/*
 *    Procedure to create widgets for the given jc.
 */
gint JCCreateWidgets(jc_struct *jc, gint argc, gchar **argv)
{
      gint border_minor = 2, border_major = 5;
        gint width, height;
        GtkWidget *w, *parent, *parent2, *parent3;
      GtkCombo *combo;
      GdkWindow *window;
      GdkColor *c;
      GdkColormap *colormap;
      GdkGCValues gcv;
      gpointer ptr_rtn;


      if(jc == NULL)
          return(-1);


      /* Reset values that apply to widgets only, all other values
       * should already be reset by the calling function.
       */
      jc->layout_state = JC_LAYOUT_REPRESENTATIVE;


      /* Toplevel. */
      jc->toplevel = w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_widget_set_usize(GTK_WIDGET(w), JC_DEF_WIDTH, JC_DEF_HEIGHT);
        gtk_window_set_title(GTK_WINDOW(w), PROG_NAME);
        gtk_window_set_policy(GTK_WINDOW(w), TRUE, TRUE, TRUE);
        gtk_widget_realize(w);
        window = w->window;
        if(window != NULL)
        {
            GdkGeometry geometry;

            geometry.min_width = 100;
            geometry.min_height = 70;

            geometry.base_width = 0;
            geometry.base_height = 0;

            geometry.width_inc = 1;
            geometry.height_inc = 1;
/*
            geometry.min_aspect = 1.3;
            geometry.max_aspect = 1.3;
 */
            gdk_window_set_geometry_hints(
                window,
                &geometry,
                GDK_HINT_MIN_SIZE |
                GDK_HINT_BASE_SIZE |
                /* GDK_HINT_ASPECT | */
                GDK_HINT_RESIZE_INC
            );

            gdk_window_set_decorations(
                window,
                GDK_DECOR_TITLE | GDK_DECOR_MENU | GDK_DECOR_MINIMIZE
            );
            gdk_window_set_functions(
                window,
                GDK_FUNC_MOVE | GDK_FUNC_RESIZE |
            GDK_FUNC_MINIMIZE | GDK_FUNC_CLOSE
            );

          GUISetWMIcon(window, (u_int8_t **)jscalibrator_xpm);
        }
        gtk_signal_connect(
            GTK_OBJECT(w), "delete_event",
            GTK_SIGNAL_FUNC(JCExitCB),
            (gpointer)jc
        );
      gtk_container_border_width(GTK_CONTAINER(w), 0);

      /* Get toplevel widget's colormap and increase its refcount
       * (since we want to keep it around).
       */
      jc->colormap = colormap = gtk_widget_get_colormap(w);
      if(jc->colormap != NULL)
          gdk_colormap_ref(jc->colormap);

        /* Create graphics context. */
      gcv.foreground.red = 0xffff;
        gcv.foreground.green = 0xffff;
        gcv.foreground.blue = 0xffff;
        gcv.background.red = 0x0000;
        gcv.background.green = 0x0000;
        gcv.background.blue = 0x0000;
        gcv.font = NULL;
        gcv.function = GDK_COPY;
        gcv.fill = GDK_SOLID;
        gcv.tile = NULL;
        gcv.stipple = NULL;
        gcv.clip_mask = NULL;
        gcv.subwindow_mode = GDK_CLIP_BY_CHILDREN;
        gcv.ts_x_origin = 0;
        gcv.ts_y_origin = 0;
        gcv.clip_x_origin = 0;
        gcv.clip_y_origin = 0;
        gcv.graphics_exposures = 0;
        gcv.line_width = 1;
        gcv.line_style = GDK_LINE_SOLID;
        gcv.cap_style = GDK_CAP_BUTT;
        gcv.join_style = GDK_JOIN_MITER;
        jc->gc = gdk_gc_new_with_values(
          window,
          &gcv,
            GDK_GC_FOREGROUND | GDK_GC_BACKGROUND |
/*        GDK_GC_FONT | */
          GDK_GC_FUNCTION | GDK_GC_FILL |
/*        GDK_GC_TILE | GDK_GC_STIPPLE |
            GDK_GC_CLIP_MASK |
 */
            GDK_GC_SUBWINDOW |
            GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN |
            GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN |
            GDK_GC_EXPOSURES | GDK_GC_LINE_WIDTH |
            GDK_GC_LINE_STYLE |
            GDK_GC_CAP_STYLE |
            GDK_GC_JOIN_STYLE
        );
      if(jc->gc == NULL)
          return(-1);


        /* Colors. */
        w = jc->toplevel;
        c = &jc->c_signal_level_bg;
        c->red = 0x0000;
        c->green = 0x0000;
        c->blue = 0x0000;
      gdk_colormap_alloc_color(colormap, c, TRUE, TRUE);

        w = jc->toplevel;
        c = &jc->c_signal_level_fg;
        c->red = 0x0000;
        c->green = 0xffff;
        c->blue = 0x0000;
        gdk_colormap_alloc_color(colormap, c, TRUE, TRUE);


      /* Main vbox. */
      parent = jc->toplevel;
      w = gtk_vbox_new(FALSE, 0);
        gtk_container_add(GTK_CONTAINER(parent), w);
        gtk_widget_show(w);
      parent = w;

      /* Menu bar. */
      w = JCCreateMenuBar(jc);
      jc->menu_bar = w;
      gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
      gtk_widget_show(w);

      /* Hbox to hold device combo and joystick signal meter drawing
       * area widgets.
       */
      w = gtk_hbox_new(FALSE, 0);
      gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
        gtk_widget_show(w);
      parent2 = w;

      /* Device combo. */
      w = (GtkWidget *)GUIComboCreate(
          "Joystick Device:",       /* Label. */
          JSDefaultDevice,          /* Initial value. */
          NULL,               /* Initial glist of items. */
          10,                       /* Max items. */
          &ptr_rtn,                 /* Combo widget return. */
          jc,                       /* Client data. */
          JCJSDeviceEntryCB,        /* Activate callback. */
          NULL                /* List change callback. */
      );
      combo = (GtkCombo *)ptr_rtn;
      jc->js_device_combo = (GtkWidget *)combo;
      gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, TRUE, 0);
      GUISetWidgetTip(
          combo->entry, HELP_TTM_DEVICES_COMBO
      );
        gtk_widget_show(w);

      /* Update combo listing. */
      JCUpateDeviceComboList(jc);


      /* Joystick signal meter frame and drawing area. */
      w = gtk_frame_new(NULL);
        gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_IN);
        gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
        gtk_widget_show(w);
      parent3 = w;

      /* Signal meter drawing area. */
        width = JC_SIGNAL_HISTORY_MAX;    /* One pixel per signal tick. */
        height = 20;
        w = gtk_drawing_area_new();
        jc->signal_level_da = w;
        gtk_drawing_area_size(GTK_DRAWING_AREA(w), width, height);
      gtk_container_add(GTK_CONTAINER(parent3), w);
        gtk_widget_realize(w);
        gtk_widget_show(w);

        jc->signal_level_pixmap = gdk_pixmap_new(
            ((jc->toplevel == NULL) ? 0 : jc->toplevel->window),
            width, height, -1
        );


      /* Horizontal paned widget to contain axises notebook and
       * buttons viewport.
       */
      w = gtk_hpaned_new();
      gtk_box_pack_start(GTK_BOX(parent), w, TRUE, TRUE, 0);
        gtk_paned_set_position(GTK_PANED(w), 480);
        gtk_paned_set_handle_size(GTK_PANED(w), 10);
        gtk_paned_set_gutter_size(GTK_PANED(w), 12);
        gtk_widget_show(w);
        parent2 = w;


      /* Notebook for axises layouts. */
      jc->axises_notebook = w = gtk_notebook_new();
        gtk_notebook_set_tab_pos(GTK_NOTEBOOK(w), GTK_POS_TOP);
      gtk_paned_add1(GTK_PANED(parent2), w);
        gtk_notebook_set_scrollable(GTK_NOTEBOOK(w), TRUE);
        gtk_notebook_set_show_tabs(GTK_NOTEBOOK(w), TRUE);
        gtk_notebook_set_show_border(GTK_NOTEBOOK(w), TRUE);
/*      gtk_notebook_set_page(GTK_NOTEBOOK(w), 0); */
        gtk_signal_connect(
            GTK_OBJECT(w), "switch_page",
            GTK_SIGNAL_FUNC(JCSwitchPageCB),
          (gpointer)jc
        );
        gtk_widget_show(w);


      /* Add vboxes into each page of the notebook. */
      /* Representative axises layout vbox. */
      jc->layout_rep_parent = w = gtk_vbox_new(FALSE, 0);
      gtk_container_border_width(GTK_CONTAINER(w), border_major);
      gtk_notebook_append_page(
            GTK_NOTEBOOK(jc->axises_notebook),
            w,
            gtk_label_new("Representative")
        );
      gtk_widget_show(w);
      jc->layout_rep_parent_client = NULL;      /* Created when needed. */

      /* Logical axises layout viewport and vbox. */
      jc->layout_logical_vp = w = gtk_scrolled_window_new(NULL, NULL);
        gtk_scrolled_window_set_policy(
            GTK_SCROLLED_WINDOW(w),
            GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC
        );
      gtk_container_border_width(GTK_CONTAINER(w), border_major);
        gtk_notebook_append_page(  
            GTK_NOTEBOOK(jc->axises_notebook),
            w,
            gtk_label_new("Logical")
        );
      gtk_widget_show(w);
      parent3 = w;
      /* Vbox. */
      jc->layout_logical_parent = w = gtk_vbox_new(FALSE, border_minor);
      gtk_container_border_width(GTK_CONTAINER(w), border_major);
        gtk_scrolled_window_add_with_viewport(
          GTK_SCROLLED_WINDOW(parent3), w
        );
        gtk_widget_show(w);


      /* Implicitly reset axis layout structures. */
      memset(&jc->layout_logical, 0x00, sizeof(layout_logical_struct));
        memset(&jc->layout_rep, 0x00, sizeof(layout_rep_struct));


        /* Viewport for buttons list vbox. */
        w = gtk_scrolled_window_new(NULL, NULL);
        jc->buttons_list_vp = w;
        gtk_paned_add2(GTK_PANED(parent2), w);
        gtk_scrolled_window_set_policy(
            GTK_SCROLLED_WINDOW(w),
          GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC
        );
        gtk_widget_show(w);
        parent3 = w;

      /* Button list vbox. */
      jc->buttons_list_parent = w = gtk_vbox_new(FALSE, 0);
      gtk_container_border_width(GTK_CONTAINER(w), 0);
        gtk_scrolled_window_add_with_viewport(
          GTK_SCROLLED_WINDOW(parent3), w
      );
      gtk_widget_show(w);


      /* Status bar. */
      StatusBarInit(&jc->status_bar, parent);
        StatusBarSetJSState(&jc->status_bar, 0);


      return(0);
}


/*
 *    Destroys all widgets on the given jc structure and resets only
 *    the values for the destroyed widgets on the jc.
 */
void JCDestroyWidgets(jc_struct *jc)
{
      GdkColor *c;
      GdkColormap *colormap;
      GdkPixmap **pixmap_ptr;
      GtkWidget **widget_ptr;


      if(jc == NULL)
          return;

      colormap = jc->colormap;

      /* Destroy axis layout structures and their widgets. */
      JCDestroyRepresentativeLayoutWidgets(jc, &jc->layout_rep);
      JCDestroyLogicalLayoutWidgets(jc, &jc->layout_logical);

      /* Destroy buttons list widgets. */
      JCDestroyButtonsList(jc);

      /* Destroy status bar. */
      StatusBarDestroy(&jc->status_bar);


      /* Destroy other widgets and resources on jc. */
#define DO_FREE_COLOR   \
{ \
 if(c != NULL) \
 { \
  gdk_colormap_free_colors(colormap, c, 1); \
  memset(c, 0x00, sizeof(GdkColor)); \
 } \
}
#define DO_UNREF_PIXMAP \
{ \
 if((*pixmap_ptr) != NULL) \
 { \
  gdk_pixmap_unref(*pixmap_ptr); \
  (*pixmap_ptr) = NULL; \
 } \
}
#define DO_DESTROY_WIDGET     \
{ \
 if((*widget_ptr) != NULL) \
 { \
  gtk_widget_destroy(*widget_ptr); \
  (*widget_ptr) = NULL; \
 } \
}
      c = &jc->c_signal_level_bg;
      DO_FREE_COLOR
      c = &jc->c_signal_level_fg;
        DO_FREE_COLOR

      pixmap_ptr = &jc->signal_level_pixmap;
      DO_UNREF_PIXMAP

      widget_ptr = &jc->menu_bar;
      DO_DESTROY_WIDGET

      widget_ptr = &jc->js_device_combo;
      DO_DESTROY_WIDGET

        widget_ptr = &jc->signal_level_da;
        DO_DESTROY_WIDGET

      widget_ptr = &jc->axises_notebook;
      DO_DESTROY_WIDGET

      widget_ptr = &jc->buttons_list_parent;
      DO_DESTROY_WIDGET

        widget_ptr = &jc->buttons_list_vp;
        DO_DESTROY_WIDGET


      widget_ptr = &jc->toplevel;
      DO_DESTROY_WIDGET

#undef DO_UNREF_PIXMAP
#undef DO_DESTROY_WIDGET
#undef DO_FREE_COLOR

      /* Unref graphics context. */
      if(jc->gc != NULL)
      {
          gdk_gc_unref(jc->gc);
          jc->gc = NULL;
      }

      /* Unref colormap. */
      if(jc->colormap != NULL)
      {
          gdk_colormap_unref(jc->colormap);
          jc->colormap = NULL;
      }
}

Generated by  Doxygen 1.6.0   Back to index