home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / devices.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  33.0 KB  |  1,253 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <string.h>
  22.  
  23. #include <glib.h>
  24.  
  25. #include "apptypes.h"
  26.  
  27. #include "appenv.h"
  28. #include "devices.h"
  29. #include "dialog_handler.h"
  30. #include "gimpcontextpreview.h"
  31. #include "gimpdnd.h"
  32. #include "gimpbrushlist.h"
  33. #include "gimpcontext.h"
  34. #include "gimprc.h"
  35. #include "gimpui.h"
  36. #include "gradient.h"
  37. #include "gradient_header.h"
  38. #include "session.h"
  39. #include "tools.h"
  40.  
  41. #include "libgimp/gimpenv.h"
  42.  
  43. #include "libgimp/gimpintl.h"
  44.  
  45. #define CELL_SIZE 20 /* The size of the preview cells */
  46.  
  47. #define PREVIEW_EVENT_MASK  GDK_BUTTON_PRESS_MASK | \
  48.                 GDK_BUTTON_RELEASE_MASK | \
  49.                 GDK_ENTER_NOTIFY_MASK | \
  50.                             GDK_LEAVE_NOTIFY_MASK
  51.  
  52. #define DEVICE_CONTEXT_MASK GIMP_CONTEXT_TOOL_MASK | \
  53.                             GIMP_CONTEXT_FOREGROUND_MASK | \
  54.                 GIMP_CONTEXT_BRUSH_MASK | \
  55.                 GIMP_CONTEXT_PATTERN_MASK | \
  56.                             GIMP_CONTEXT_GRADIENT_MASK
  57.  
  58. typedef struct _DeviceInfo DeviceInfo;
  59.  
  60. struct _DeviceInfo
  61. {
  62.   guint32       device;      /*  device ID  */
  63.   gchar        *name;
  64.  
  65.   gshort        is_present;  /*  is the device currently present  */
  66.  
  67.   /*  gdk_input options - for not present devices  */
  68.  
  69.   GdkInputMode  mode;
  70.   gint          num_axes;
  71.   GdkAxisUse   *axes;
  72.   gint          num_keys;
  73.   GdkDeviceKey *keys;
  74.  
  75.   GimpContext  *context;
  76. };
  77.  
  78. typedef struct _DeviceInfoDialog DeviceInfoDialog;
  79.  
  80. struct _DeviceInfoDialog
  81. {
  82.   gint       num_devices;
  83.  
  84.   guint32    current;
  85.   guint32   *ids;
  86.  
  87.   GtkWidget *shell;
  88.   GtkWidget *table;
  89.  
  90.   GtkWidget **frames;
  91.   GtkWidget **tools;
  92.   GtkWidget **colors;
  93.   GtkWidget **brushes;
  94.   GtkWidget **patterns;
  95.   GtkWidget **gradients;
  96.   GtkWidget **eventboxes;
  97. };
  98.  
  99. /*  local functions */
  100. static void     input_dialog_able_callback     (GtkWidget *w, guint32 deviceid, 
  101.                         gpointer data);
  102.  
  103. static void     devices_write_rc_device        (DeviceInfo *device_info,
  104.                         FILE *fp);
  105. static void     devices_write_rc               (void);
  106.  
  107. static void     device_status_destroy_callback (void);
  108. static void     devices_close_callback         (GtkWidget *, gpointer);
  109.  
  110. static void     device_status_update           (guint32 deviceid);
  111. static void     device_status_update_current   (void);
  112.  
  113. static ToolType device_status_drag_tool        (GtkWidget *,
  114.                         gpointer);
  115. static void     device_status_drop_tool        (GtkWidget *,
  116.                         ToolType,
  117.                         gpointer);
  118. static void     device_status_drag_color       (GtkWidget *,
  119.                         guchar *, guchar *, guchar *,
  120.                         gpointer);
  121. static void     device_status_drop_color       (GtkWidget *,
  122.                         guchar, guchar, guchar,
  123.                         gpointer);
  124. static void     device_status_drop_brush       (GtkWidget *,
  125.                         GimpBrush *,
  126.                         gpointer);
  127. static void     device_status_drop_pattern     (GtkWidget *,
  128.                         GPattern *,
  129.                         gpointer);
  130. static void     device_status_drop_gradient    (GtkWidget *,
  131.                         gradient_t *,
  132.                         gpointer);
  133.  
  134. static void     device_status_color_changed    (GimpContext *context,
  135.                         gint         r,
  136.                         gint         g,
  137.                         gint         b,
  138.                         gpointer     data);
  139. static void     device_status_data_changed     (GimpContext *context,
  140.                         gpointer     dummy,
  141.                         gpointer     data);
  142.  
  143. static void     device_status_context_connect  (GimpContext *context,
  144.                         guint32      deviceid);
  145.  
  146. /*  global data  */
  147. gint current_device = GDK_CORE_POINTER;
  148.  
  149. /*  local data  */
  150. static GList            *device_info_list = NULL;
  151. static DeviceInfoDialog *deviceD          = NULL;
  152.  
  153. /*  if true, don't update device information dialog */
  154. static gboolean          suppress_update  = FALSE;
  155.  
  156. /*  dnd stuff  */
  157. static GtkTargetEntry tool_target_table[] =
  158. {
  159.   GIMP_TARGET_TOOL
  160. };
  161. static guint n_tool_targets = (sizeof (tool_target_table) /
  162.                    sizeof (tool_target_table[0]));
  163.  
  164. static GtkTargetEntry color_area_target_table[] =
  165. {
  166.   GIMP_TARGET_COLOR
  167. };
  168. static guint n_color_area_targets = (sizeof (color_area_target_table) /
  169.                      sizeof (color_area_target_table[0]));
  170.  
  171. /*  utility functions for the device lists  */
  172.  
  173. static GdkDeviceInfo *
  174. gdk_device_info_get_by_id (guint32 deviceid)
  175. {
  176.   GdkDeviceInfo *info;
  177.   GList *list;
  178.  
  179.   for (list = gdk_input_list_devices (); list; list = g_list_next (list))
  180.     {
  181.       info = (GdkDeviceInfo *) list->data;
  182.  
  183.       if (info->deviceid == deviceid)
  184.     return info;
  185.     }
  186.  
  187.   return NULL;
  188. }
  189.  
  190. static DeviceInfo *
  191. device_info_get_by_id (guint32 deviceid)
  192. {
  193.   DeviceInfo *info;
  194.   GList *list;
  195.  
  196.   for (list = device_info_list; list; list = g_list_next (list))
  197.     {
  198.       info = (DeviceInfo *) list->data;
  199.  
  200.       if (info->device == deviceid)
  201.     return info;
  202.     }
  203.  
  204.   return NULL;
  205. }
  206.  
  207. static DeviceInfo *
  208. device_info_get_by_name (gchar *name)
  209. {
  210.   DeviceInfo *info;
  211.   GList *list;
  212.  
  213.   for (list = device_info_list; list; list = g_list_next (list))
  214.     {
  215.       info = (DeviceInfo *) list->data;
  216.  
  217.       if (!strcmp (info->name, name))
  218.     return info;
  219.     }
  220.  
  221.   return NULL;
  222. }
  223.  
  224. /*  the gtk input dialog  */
  225.  
  226. void 
  227. input_dialog_create (void)
  228. {
  229.   static GtkWidget *inputd = NULL;
  230.   GtkWidget        *hbbox;
  231.  
  232.   if (!inputd)
  233.     {
  234.       inputd = gtk_input_dialog_new ();
  235.  
  236.       /* register this one only */
  237.       dialog_register (inputd);
  238.  
  239.       gtk_container_set_border_width
  240.     (GTK_CONTAINER (GTK_DIALOG (inputd)->action_area), 2);
  241.       gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (inputd)->action_area),
  242.                    FALSE);
  243.  
  244.       hbbox = gtk_hbutton_box_new ();
  245.       gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbbox), 4);
  246.  
  247.       gtk_widget_reparent (GTK_INPUT_DIALOG (inputd)->save_button, hbbox);
  248.       GTK_WIDGET_SET_FLAGS (GTK_INPUT_DIALOG (inputd)->save_button,
  249.                 GTK_CAN_DEFAULT);
  250.       gtk_widget_reparent (GTK_INPUT_DIALOG (inputd)->close_button, hbbox);
  251.       GTK_WIDGET_SET_FLAGS (GTK_INPUT_DIALOG (inputd)->close_button,
  252.                 GTK_CAN_DEFAULT);
  253.  
  254.       gtk_box_pack_end (GTK_BOX (GTK_DIALOG (inputd)->action_area), hbbox,
  255.             FALSE, FALSE, 0);
  256.       gtk_widget_grab_default (GTK_INPUT_DIALOG (inputd)->close_button);
  257.       gtk_widget_show(hbbox);
  258.  
  259.       gtk_signal_connect (GTK_OBJECT (GTK_INPUT_DIALOG (inputd)->save_button),
  260.               "clicked",
  261.               GTK_SIGNAL_FUNC (devices_write_rc),
  262.               NULL);
  263.       gtk_signal_connect (GTK_OBJECT (GTK_INPUT_DIALOG (inputd)->close_button),
  264.               "clicked",
  265.               GTK_SIGNAL_FUNC (devices_close_callback),
  266.               inputd);
  267.  
  268.       gtk_signal_connect (GTK_OBJECT (inputd), "destroy",
  269.               GTK_SIGNAL_FUNC (gtk_widget_destroyed),
  270.               &inputd);
  271.  
  272.       gtk_signal_connect (GTK_OBJECT (inputd), "enable_device",
  273.               GTK_SIGNAL_FUNC (input_dialog_able_callback),
  274.               NULL);
  275.       gtk_signal_connect (GTK_OBJECT (inputd), "disable_device",
  276.               GTK_SIGNAL_FUNC (input_dialog_able_callback),
  277.               NULL);
  278.  
  279.       /*  Connect the "F1" help key  */
  280.       gimp_help_connect_help_accel (inputd,
  281.                     gimp_standard_help_func,
  282.                     "dialogs/input_devices.html");
  283.  
  284.       gtk_widget_show (inputd);
  285.     }
  286.   else
  287.     {
  288.       if (!GTK_WIDGET_MAPPED (inputd))
  289.     gtk_widget_show (inputd);
  290.       else
  291.     gdk_window_raise (inputd->window);
  292.     }
  293. }
  294.  
  295. static void
  296. input_dialog_able_callback (GtkWidget *widget,
  297.                 guint32    deviceid,
  298.                 gpointer   data)
  299. {
  300.   device_status_update (deviceid);
  301. }
  302.  
  303. void 
  304. devices_init (void)
  305. {
  306.   GdkDeviceInfo *gdk_info;
  307.   DeviceInfo    *device_info;
  308.   GList         *list;
  309.  
  310.   /*  create device info structures for present devices */
  311.   for (list = gdk_input_list_devices (); list; list = g_list_next (list))
  312.     {
  313.       gdk_info = (GdkDeviceInfo *) list->data;
  314.  
  315.       device_info = g_new (DeviceInfo, 1);
  316.  
  317.       device_info->device     = gdk_info->deviceid;
  318.       device_info->name       = g_strdup (gdk_info->name);
  319.       device_info->is_present = TRUE;
  320.  
  321.       device_info->mode       = gdk_info->mode;
  322.       device_info->num_axes   = gdk_info->num_axes;
  323.       device_info->axes       = NULL;
  324.  
  325.       device_info->context    = gimp_context_new (device_info->name, NULL);
  326.       gimp_context_define_args (device_info->context,
  327.                 DEVICE_CONTEXT_MASK,
  328.                 FALSE);
  329.       gimp_context_copy_args (gimp_context_get_user (), device_info->context,
  330.                   DEVICE_CONTEXT_MASK);
  331.       device_status_context_connect (device_info->context, device_info->device);
  332.  
  333.       device_info_list = g_list_append (device_info_list, device_info);
  334.     }
  335. }
  336.  
  337. void
  338. devices_restore (void)
  339. {
  340.   DeviceInfo *device_info;
  341.   GimpContext *context;
  342.   gchar *filename;
  343.  
  344.   /* Augment with information from rc file */
  345.   filename = gimp_personal_rc_file ("devicerc");
  346.   parse_gimprc_file (filename);
  347.   g_free (filename);
  348.  
  349.   if ((device_info = device_info_get_by_id (current_device)) == NULL)
  350.     return;
  351.  
  352.   suppress_update = TRUE;
  353.  
  354.   context = gimp_context_get_user ();
  355.  
  356.   gimp_context_copy_args (device_info->context, context, DEVICE_CONTEXT_MASK);
  357.   gimp_context_set_parent (device_info->context, context);
  358.   
  359.   suppress_update = FALSE;
  360. }
  361.  
  362. void
  363. devices_rc_update (gchar        *name, 
  364.            DeviceValues  values,
  365.            GdkInputMode  mode, 
  366.            gint          num_axes,
  367.            GdkAxisUse   *axes, 
  368.            gint          num_keys, 
  369.            GdkDeviceKey *keys,
  370.            ToolType      tool,
  371.            guchar        foreground[], 
  372.            guchar        background[],
  373.            gchar        *brush_name, 
  374.            gchar        *pattern_name,
  375.            gchar        *gradient_name)
  376. {
  377.   DeviceInfo *device_info;
  378.  
  379.   /*  Find device if we have it  */
  380.   device_info = device_info_get_by_name (name);
  381.  
  382.   if (!device_info)
  383.     {
  384.       device_info = g_new (DeviceInfo, 1);
  385.       device_info->name = g_strdup (name);
  386.       device_info->is_present = FALSE;
  387.  
  388.       if (values & DEVICE_AXES)
  389.     {
  390.       device_info->num_axes = num_axes;
  391.       device_info->axes = g_new (GdkAxisUse, num_axes);
  392.       memcpy (device_info->axes, axes, num_axes * sizeof (GdkAxisUse));
  393.     }
  394.       else
  395.     {
  396.       device_info->num_axes = 0;
  397.       device_info->axes = NULL;
  398.     }
  399.  
  400.       if (values & DEVICE_KEYS)
  401.     {
  402.       device_info->num_keys = num_keys;
  403.       device_info->keys = g_new (GdkDeviceKey, num_keys);
  404.       memcpy (device_info->keys, axes, num_keys * sizeof (GdkDeviceKey));
  405.     }
  406.  
  407.       if (values & DEVICE_MODE)
  408.     device_info->mode = mode;
  409.       else
  410.     device_info->mode = GDK_MODE_DISABLED;
  411.  
  412.       device_info->context = gimp_context_new (device_info->name, NULL);
  413.       gimp_context_define_args (device_info->context,
  414.                 DEVICE_CONTEXT_MASK,
  415.                 FALSE);
  416.       gimp_context_copy_args (gimp_context_get_user (), device_info->context,
  417.                   DEVICE_CONTEXT_MASK);
  418.       device_status_context_connect (device_info->context, device_info->device);
  419.  
  420.       device_info_list = g_list_append (device_info_list, device_info);
  421.     }
  422.   else
  423.     {
  424.       GdkDeviceInfo *gdk_info;
  425.  
  426.       gdk_info = gdk_device_info_get_by_id (device_info->device);
  427.  
  428.       if (gdk_info != NULL)
  429.     {
  430.       if (values & DEVICE_MODE)
  431.         gdk_input_set_mode (gdk_info->deviceid, mode);
  432.       
  433.       if ((values & DEVICE_AXES) && num_axes >= gdk_info->num_axes)
  434.         gdk_input_set_axes (gdk_info->deviceid, axes);
  435.  
  436.       if ((values & DEVICE_KEYS) && num_keys >= gdk_info->num_keys)
  437.         {
  438.           gint i;
  439.           
  440.           for (i=0; i<MAX (num_keys, gdk_info->num_keys); i++)
  441.         gdk_input_set_key (gdk_info->deviceid, i,
  442.                    keys[i].keyval, keys[i].modifiers);
  443.         }
  444.     }
  445.       else
  446.     {
  447.       g_warning ("devices_rc_update called multiple times "
  448.              "for not present device\n");
  449.       return;
  450.     }
  451.     }
  452.  
  453.   if (values & DEVICE_TOOL)
  454.     {
  455.       gimp_context_set_tool (device_info->context, tool);
  456.     }
  457.  
  458.   if (values & DEVICE_FOREGROUND)
  459.     {
  460.       gimp_context_set_foreground (device_info->context,
  461.                    foreground[0],
  462.                    foreground[1],
  463.                    foreground[2]);
  464.     }
  465.  
  466.   if (values & DEVICE_BACKGROUND)
  467.     {
  468.       gimp_context_set_background (device_info->context,
  469.                    background[0],
  470.                    background[1],
  471.                    background[2]);
  472.     }
  473.  
  474.   if (values & DEVICE_BRUSH)
  475.     {
  476.       GimpBrush *brush;
  477.  
  478.       brush = gimp_brush_list_get_brush (brush_list, brush_name);
  479.  
  480.       if (brush)
  481.     {
  482.       gimp_context_set_brush (device_info->context, brush);
  483.     }
  484.       else if (no_data)
  485.     {
  486.       g_free (device_info->context->brush_name);
  487.       device_info->context->brush_name = g_strdup (brush_name);
  488.     }
  489.     }
  490.  
  491.   if (values & DEVICE_PATTERN)
  492.     {
  493.       GPattern *pattern;
  494.  
  495.       pattern = pattern_list_get_pattern (pattern_list, pattern_name);
  496.  
  497.       if (pattern)
  498.     {
  499.       gimp_context_set_pattern (device_info->context, pattern);
  500.     }
  501.       else if (no_data)
  502.     {
  503.       g_free (device_info->context->pattern_name);
  504.       device_info->context->pattern_name = g_strdup (pattern_name);
  505.     }
  506.     }
  507.  
  508.   if (values & DEVICE_GRADIENT)
  509.     {
  510.       gradient_t *gradient;
  511.  
  512.       gradient = gradient_list_get_gradient (gradients_list, gradient_name);
  513.  
  514.       if (gradient)
  515.     {
  516.       gimp_context_set_gradient (device_info->context, gradient);
  517.     }
  518.       else if (no_data)
  519.     {
  520.       g_free (device_info->context->gradient_name);
  521.       device_info->context->gradient_name = g_strdup (gradient_name);
  522.     }
  523.     }
  524. }
  525.  
  526. void
  527. select_device (guint32 new_device)
  528. {
  529.   DeviceInfo *device_info;
  530.   GimpContext *context;
  531.  
  532.   device_info = device_info_get_by_id (current_device);
  533.  
  534.   gimp_context_unset_parent (device_info->context);
  535.  
  536.   suppress_update = TRUE;
  537.   
  538.   device_info = device_info_get_by_id (new_device);
  539.  
  540.   current_device = new_device;
  541.  
  542.   context = gimp_context_get_user ();
  543.  
  544.   gimp_context_copy_args (device_info->context, context, DEVICE_CONTEXT_MASK);
  545.   gimp_context_set_parent (device_info->context, context);
  546.  
  547.   suppress_update = FALSE;
  548.  
  549.   device_status_update_current ();
  550. }
  551.  
  552. gint
  553. devices_check_change (GdkEvent *event)
  554. {
  555.   guint32 device;
  556.  
  557.   switch (event->type)
  558.     {
  559.     case GDK_MOTION_NOTIFY:
  560.       device = ((GdkEventMotion *)event)->deviceid;
  561.       break;
  562.     case GDK_BUTTON_PRESS:
  563.     case GDK_BUTTON_RELEASE:
  564.       device = ((GdkEventButton *)event)->deviceid;
  565.       break;
  566.     case GDK_PROXIMITY_OUT:
  567.       device = ((GdkEventProximity *)event)->deviceid;
  568.       break;
  569.     default:
  570.       device = current_device;
  571.     }
  572.  
  573.   if (device != current_device)
  574.     {
  575.       select_device (device);
  576.       return TRUE;
  577.     }
  578.   else
  579.     {
  580.       return FALSE;
  581.     }
  582. }
  583.  
  584. static void
  585. devices_write_rc_device (DeviceInfo *device_info,
  586.              FILE       *fp)
  587. {
  588.   GdkDeviceInfo *gdk_info = NULL;
  589.   gchar *mode = NULL;
  590.   gint i;
  591.  
  592.   if (device_info->is_present)
  593.     gdk_info = gdk_device_info_get_by_id (device_info->device);
  594.   
  595.   fprintf (fp, "(device \"%s\"", device_info->name);
  596.  
  597.   switch (gdk_info ? gdk_info->mode : device_info->mode)
  598.     {
  599.     case GDK_MODE_DISABLED:
  600.       mode = "disabled";
  601.       break;
  602.     case GDK_MODE_SCREEN:
  603.       mode = "screen";
  604.       break;
  605.     case GDK_MODE_WINDOW:
  606.       mode = "window";
  607.       break;
  608.     }
  609.   
  610.   fprintf (fp, "\n        (mode %s)", mode);
  611.  
  612.   fprintf (fp, "\n        (axes %d",
  613.        gdk_info ? gdk_info->num_axes : device_info->num_axes);
  614.  
  615.   for (i=0; i< (gdk_info ? gdk_info->num_axes : device_info->num_axes); i++)
  616.     {
  617.       gchar *axis_type = NULL;    /* Quiet gcc */
  618.  
  619.       switch (gdk_info ? gdk_info->axes[i] : device_info->axes[i])
  620.     {
  621.     case GDK_AXIS_IGNORE:
  622.       axis_type = "ignore";
  623.       break;
  624.     case GDK_AXIS_X:
  625.       axis_type = "x";
  626.       break;
  627.     case GDK_AXIS_Y:
  628.       axis_type = "y";
  629.       break;
  630.     case GDK_AXIS_PRESSURE:
  631.       axis_type = "pressure";
  632.       break;
  633.     case GDK_AXIS_XTILT:
  634.       axis_type = "xtilt";
  635.       break;
  636.     case GDK_AXIS_YTILT:
  637.       axis_type = "ytilt";
  638.       break;
  639. #ifdef GTK_HAVE_SIX_VALUATORS
  640.     case GDK_AXIS_WHEEL:
  641.       axis_type = "wheel";
  642.       break;
  643. #endif /* GTK_HAVE_SIX_VALUATORS */
  644.     }
  645.       fprintf (fp, " %s",axis_type);
  646.     }
  647.   fprintf (fp,")");
  648.  
  649.   fprintf (fp, "\n        (keys %d",
  650.        gdk_info ? gdk_info->num_keys : device_info->num_keys);
  651.  
  652.   for (i=0; i < (gdk_info ? gdk_info->num_keys : device_info->num_keys); i++)
  653.     {
  654.       GdkModifierType modifiers = gdk_info ? gdk_info->keys[i].modifiers :
  655.     device_info->keys[i].modifiers;
  656.       guint keyval = gdk_info ? gdk_info->keys[i].keyval :
  657.     device_info->keys[i].keyval;
  658.  
  659.       if (keyval)
  660.     {
  661.       /* FIXME: integrate this back with menus_install_accelerator */
  662.       gchar accel[64];
  663.       gchar t2[2];
  664.  
  665.       accel[0] = '\0';
  666.       if (modifiers & GDK_CONTROL_MASK)
  667.         strcat (accel, "<control>");
  668.       if (modifiers & GDK_SHIFT_MASK)
  669.         strcat (accel, "<shift>");
  670.       if (modifiers & GDK_MOD1_MASK)
  671.         strcat (accel, "<alt>");
  672.       
  673.       t2[0] = keyval;
  674.       t2[1] = '\0';
  675.       strcat (accel, t2);
  676.       fprintf (fp, " \"%s\"",accel);
  677.     }
  678.       else
  679.     fprintf (fp, " \"\"");
  680.     }
  681.   fprintf (fp,")");
  682.  
  683.   /* Fixme: hard coded last tool....  see gimprc */
  684.   if (gimp_context_get_tool (device_info->context) >= FIRST_TOOLBOX_TOOL &&
  685.       gimp_context_get_tool (device_info->context) <= LAST_TOOLBOX_TOOL)
  686.     {
  687.       fprintf (fp, "\n        (tool \"%s\")",
  688.            tool_info[gimp_context_get_tool (device_info->context)].tool_name);
  689.     }
  690.  
  691.   {
  692.     guchar r, g, b;
  693.     gimp_context_get_foreground (device_info->context, &r, &g, &b);
  694.     fprintf (fp, "\n        (foreground %d %d %d)", r, g, b);
  695.   }
  696.  
  697.   if (gimp_context_get_brush (device_info->context))
  698.     {
  699.       fprintf (fp, "\n        (brush \"%s\")",
  700.            gimp_context_get_brush (device_info->context)->name);
  701.     }
  702.  
  703.   if (gimp_context_get_pattern (device_info->context))
  704.     {
  705.       fprintf (fp, "\n        (pattern \"%s\")",
  706.            gimp_context_get_pattern (device_info->context)->name);
  707.     }
  708.  
  709.   if (gimp_context_get_gradient (device_info->context))
  710.     {
  711.       fprintf (fp, "\n        (gradient \"%s\")",
  712.            gimp_context_get_gradient (device_info->context)->name);
  713.     }
  714.  
  715.   fprintf(fp,")\n");
  716. }
  717.  
  718. static void
  719. devices_write_rc (void)
  720. {
  721.   DeviceInfo *device_info;
  722.   gchar *filename;
  723.   FILE *fp;
  724.  
  725.   device_info = device_info_get_by_id (current_device);
  726.  
  727.   filename = gimp_personal_rc_file ("devicerc");
  728.   fp = fopen (filename, "wb");
  729.   g_free (filename);
  730.  
  731.   if (!fp)
  732.     return;
  733.  
  734.   g_list_foreach (device_info_list, (GFunc) devices_write_rc_device, fp);
  735.  
  736.   fclose (fp);
  737. }
  738.  
  739. void 
  740. device_status_create (void)
  741. {
  742.   DeviceInfo *device_info;
  743.   GtkWidget *label;
  744.   GList *list;
  745.   gint i;
  746.   
  747.   if (deviceD == NULL)
  748.     {
  749.       deviceD = g_new (DeviceInfoDialog, 1);
  750.  
  751.       deviceD->shell =
  752.     gimp_dialog_new (_("Device Status"), "device_status",
  753.              gimp_standard_help_func,
  754.              "dialogs/device_status.html",
  755.              GTK_WIN_POS_NONE,
  756.              FALSE, FALSE, TRUE,
  757.  
  758.              _("Save"), (GtkSignalFunc) devices_write_rc,
  759.              NULL, NULL, NULL, FALSE, FALSE,
  760.              _("Close"), devices_close_callback,
  761.              NULL, NULL, NULL, TRUE, TRUE,
  762.  
  763.              NULL);
  764.  
  765.       dialog_register (deviceD->shell);
  766.       session_set_window_geometry (deviceD->shell, &device_status_session_info,
  767.                    FALSE);
  768.  
  769.       deviceD->num_devices = 0;
  770.  
  771.       for (list = device_info_list; list; list = g_list_next (list))
  772.     {
  773.       if (((DeviceInfo *) list->data)->is_present)
  774.         deviceD->num_devices++;
  775.     }
  776.  
  777.       /*  devices table  */
  778.       deviceD->table = gtk_table_new (deviceD->num_devices, 6, FALSE);
  779.       gtk_container_set_border_width (GTK_CONTAINER (deviceD->table), 3);
  780.       gtk_container_add (GTK_CONTAINER (GTK_DIALOG (deviceD->shell)->vbox),
  781.              deviceD->table);
  782.       gtk_widget_realize (deviceD->table);
  783.       gtk_widget_show (deviceD->table);
  784.  
  785.       deviceD->ids        = g_new (guint32, deviceD->num_devices);
  786.       deviceD->frames     = g_new (GtkWidget *, deviceD->num_devices);
  787.       deviceD->tools      = g_new (GtkWidget *, deviceD->num_devices);
  788.       deviceD->colors     = g_new (GtkWidget *, deviceD->num_devices);
  789.       deviceD->brushes    = g_new (GtkWidget *, deviceD->num_devices);
  790.       deviceD->patterns   = g_new (GtkWidget *, deviceD->num_devices);
  791.       deviceD->gradients  = g_new (GtkWidget *, deviceD->num_devices);
  792.       deviceD->eventboxes = g_new (GtkWidget *, deviceD->num_devices);
  793.  
  794.       for (list = device_info_list, i = 0; list; list = g_list_next (list), i++)
  795.     {
  796.       if (!((DeviceInfo *) list->data)->is_present)
  797.         continue;
  798.  
  799.       device_info = (DeviceInfo *) list->data;
  800.  
  801.       deviceD->ids[i] = device_info->device;
  802.  
  803.       /*  the device name  */
  804.  
  805.       deviceD->frames[i] = gtk_frame_new (NULL);
  806.  
  807.       gtk_frame_set_shadow_type (GTK_FRAME(deviceD->frames[i]),
  808.                      GTK_SHADOW_OUT);
  809.       gtk_table_attach (GTK_TABLE(deviceD->table), deviceD->frames[i],
  810.                 0, 1, i, i+1,
  811.                 GTK_FILL, GTK_FILL, 2, 0);
  812.  
  813.       label = gtk_label_new (device_info->name);
  814.       gtk_misc_set_padding (GTK_MISC(label), 2, 0);
  815.       gtk_container_add (GTK_CONTAINER(deviceD->frames[i]), label);
  816.       gtk_widget_show(label);
  817.  
  818.       /*  the tool  */
  819.  
  820.       deviceD->eventboxes[i] = gtk_event_box_new();
  821.  
  822.       deviceD->tools[i] = gtk_pixmap_new (tool_get_pixmap (RECT_SELECT), 
  823.                           tool_get_mask (RECT_SELECT));
  824.       
  825.       gtk_drag_source_set (deviceD->eventboxes[i],
  826.                    GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
  827.                    tool_target_table, n_tool_targets,
  828.                    GDK_ACTION_COPY);
  829.       gimp_dnd_tool_source_set (deviceD->eventboxes[i],
  830.                     device_status_drag_tool, 
  831.                     GUINT_TO_POINTER (device_info->device));
  832.        gtk_drag_dest_set (deviceD->eventboxes[i],
  833.                   GTK_DEST_DEFAULT_HIGHLIGHT |
  834.                  GTK_DEST_DEFAULT_MOTION |
  835.                   GTK_DEST_DEFAULT_DROP,
  836.                   tool_target_table, n_tool_targets,
  837.                   GDK_ACTION_COPY); 
  838.        gimp_dnd_tool_dest_set (deviceD->eventboxes[i],
  839.                   device_status_drop_tool, 
  840.                   GUINT_TO_POINTER (device_info->device));
  841.       gtk_container_add (GTK_CONTAINER (deviceD->eventboxes[i]),
  842.                  deviceD->tools[i]);
  843.       gtk_table_attach (GTK_TABLE (deviceD->table), deviceD->eventboxes[i],
  844.                 1, 2, i, i+1,
  845.                 0, 0, 2, 2);
  846.  
  847.       /*  the foreground color  */
  848.  
  849.       deviceD->colors[i] = gtk_preview_new (GTK_PREVIEW_COLOR);
  850.       gtk_widget_set_events (deviceD->colors[i], PREVIEW_EVENT_MASK);
  851.       gtk_preview_size (GTK_PREVIEW (deviceD->colors[i]),
  852.                 CELL_SIZE, CELL_SIZE);
  853.       gtk_drag_source_set (deviceD->colors[i],
  854.                    GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
  855.                    color_area_target_table, n_color_area_targets,
  856.                    GDK_ACTION_COPY);
  857.       gimp_dnd_color_source_set (deviceD->colors[i],
  858.                      device_status_drag_color, 
  859.                      GUINT_TO_POINTER (device_info->device));
  860.        gtk_drag_dest_set (deviceD->colors[i],
  861.                   GTK_DEST_DEFAULT_HIGHLIGHT |
  862.                  GTK_DEST_DEFAULT_MOTION |
  863.                   GTK_DEST_DEFAULT_DROP,
  864.                   color_area_target_table, n_color_area_targets,
  865.                   GDK_ACTION_COPY); 
  866.        gimp_dnd_color_dest_set (deviceD->colors[i], device_status_drop_color, 
  867.                    GUINT_TO_POINTER (device_info->device));
  868.       gtk_table_attach (GTK_TABLE(deviceD->table), deviceD->colors[i],
  869.                 2, 3, i, i+1,
  870.                 0, 0, 2, 2);
  871.  
  872.       /*  the brush  */
  873.  
  874.       deviceD->brushes[i] =
  875.         gimp_context_preview_new (GCP_BRUSH, 
  876.                       CELL_SIZE, CELL_SIZE,
  877.                       FALSE, TRUE,
  878.                       GTK_SIGNAL_FUNC (device_status_drop_brush),
  879.                       GUINT_TO_POINTER (device_info->device));
  880.       gtk_table_attach (GTK_TABLE(deviceD->table), deviceD->brushes[i],
  881.                 3, 4, i, i+1,
  882.                 0, 0, 2, 2);
  883.  
  884.       /*  the pattern  */
  885.  
  886.       deviceD->patterns[i] =
  887.         gimp_context_preview_new (GCP_PATTERN,
  888.                       CELL_SIZE, CELL_SIZE, 
  889.                       FALSE, TRUE,
  890.                       GTK_SIGNAL_FUNC (device_status_drop_pattern),
  891.                       GUINT_TO_POINTER (device_info->device));
  892.       gtk_table_attach (GTK_TABLE(deviceD->table), deviceD->patterns[i],
  893.                 4, 5, i, i+1,
  894.                 0, 0, 2, 2);
  895.  
  896.       /*  the gradient  */
  897.  
  898.       deviceD->gradients[i] =
  899.         gimp_context_preview_new (GCP_GRADIENT,
  900.                       CELL_SIZE * 2, CELL_SIZE, 
  901.                       FALSE, TRUE,
  902.                       GTK_SIGNAL_FUNC (device_status_drop_gradient),
  903.                       GUINT_TO_POINTER (device_info->device));
  904.       gtk_table_attach (GTK_TABLE(deviceD->table), deviceD->gradients[i],
  905.                 5, 6, i, i+1,
  906.                 0, 0, 2, 2);
  907.  
  908.       device_status_update (device_info->device);
  909.     }
  910.  
  911.       deviceD->current = 0xffffffff; /* random, but doesn't matter */
  912.       device_status_update_current ();
  913.  
  914.       gtk_widget_show (deviceD->shell);
  915.  
  916.       gtk_signal_connect (GTK_OBJECT (deviceD->shell), "destroy",
  917.               GTK_SIGNAL_FUNC (device_status_destroy_callback),
  918.               NULL);
  919.     }
  920.   else
  921.     {
  922.       if (!GTK_WIDGET_MAPPED (deviceD->shell))
  923.     gtk_widget_show (deviceD->shell);
  924.       else
  925.     gdk_window_raise (deviceD->shell->window);
  926.     }
  927. }
  928.  
  929. static void
  930. device_status_destroy_callback (void)
  931. {
  932.   g_free (deviceD->ids);
  933.   g_free (deviceD->frames);
  934.   g_free (deviceD->tools);
  935.   g_free (deviceD->eventboxes);
  936.   g_free (deviceD->colors);
  937.   g_free (deviceD->brushes);
  938.   g_free (deviceD->patterns);
  939.   g_free (deviceD->gradients);
  940.  
  941.   g_free (deviceD);
  942.   deviceD = NULL;
  943. }
  944.  
  945. static void
  946. devices_close_callback (GtkWidget *widget,
  947.             gpointer   data)
  948. {
  949.   gtk_widget_hide (GTK_WIDGET (data));
  950. }
  951.  
  952. void
  953. device_status_free (void)
  954. {                                     
  955.   /* Save device status on exit */
  956.   if (save_device_status)
  957.     devices_write_rc ();
  958.  
  959.   if (deviceD)
  960.     {
  961.       session_get_window_info (deviceD->shell, &device_status_session_info);
  962.       device_status_destroy_callback (); 
  963.     }
  964. }
  965.  
  966. static void
  967. device_status_update_current (void)
  968. {
  969.   gint i;
  970.  
  971.   if (deviceD)
  972.     {
  973.       for (i = 0; i < deviceD->num_devices; i++)
  974.     {
  975.       if (deviceD->ids[i] == deviceD->current)
  976.         gtk_frame_set_shadow_type (GTK_FRAME(deviceD->frames[i]), 
  977.                        GTK_SHADOW_OUT);
  978.       else if (deviceD->ids[i] == current_device)
  979.         gtk_frame_set_shadow_type (GTK_FRAME(deviceD->frames[i]), 
  980.                        GTK_SHADOW_IN);
  981.     }
  982.  
  983.       deviceD->current = current_device;
  984.     }
  985. }
  986.  
  987. void 
  988. device_status_update (guint32 deviceid)
  989. {
  990.   GdkDeviceInfo *gdk_info;
  991.   DeviceInfo    *device_info;
  992.   guchar buffer[CELL_SIZE*3];
  993.   gchar  ttbuf[20]; /* [xxx,xxx,xxx] + null */
  994.   gint   i, j;
  995.  
  996.   if (!deviceD || suppress_update)
  997.     return;
  998.  
  999.   if ((device_info = device_info_get_by_id (deviceid)) == NULL)
  1000.     return;
  1001.  
  1002.   if ((gdk_info = gdk_device_info_get_by_id (deviceid)) == NULL)
  1003.     return;
  1004.  
  1005.   for (i = 0; i < deviceD->num_devices; i++)
  1006.     {
  1007.       if (deviceD->ids[i] == deviceid)
  1008.     break;
  1009.     }
  1010.  
  1011.   g_return_if_fail (i < deviceD->num_devices);
  1012.  
  1013.   if (gdk_info->mode == GDK_MODE_DISABLED)
  1014.     {
  1015.       gtk_widget_hide (deviceD->frames[i]);
  1016.       gtk_widget_hide (deviceD->tools[i]);
  1017.       gtk_widget_hide (deviceD->eventboxes[i]);
  1018.       gtk_widget_hide (deviceD->colors[i]);
  1019.       gtk_widget_hide (deviceD->brushes[i]);
  1020.       gtk_widget_hide (deviceD->patterns[i]);
  1021.       gtk_widget_hide (deviceD->gradients[i]);
  1022.     }
  1023.   else
  1024.     {
  1025.       gtk_widget_show (deviceD->frames[i]);
  1026.  
  1027.       gtk_pixmap_set (GTK_PIXMAP (deviceD->tools[i]), 
  1028.               tool_get_pixmap (gimp_context_get_tool (device_info->context)),
  1029.               tool_get_mask (gimp_context_get_tool (device_info->context)));
  1030.  
  1031.       gtk_widget_draw (deviceD->tools[i], NULL);
  1032.       gtk_widget_show (deviceD->tools[i]);
  1033.       gtk_widget_show (deviceD->eventboxes[i]);
  1034.  
  1035.       gimp_help_set_help_data (deviceD->eventboxes[i],
  1036.                    tool_info[(gint) gimp_context_get_tool (device_info->context)].tool_desc,
  1037.                    tool_info[(gint) gimp_context_get_tool (device_info->context)].private_tip);
  1038.  
  1039.       for (j = 0; j < CELL_SIZE * 3; j += 3)
  1040.     {
  1041.       gimp_context_get_foreground (device_info->context,
  1042.                        &buffer[j],
  1043.                        &buffer[j+1],
  1044.                        &buffer[j+2]);
  1045.     }
  1046.  
  1047.       for (j = 0; j < CELL_SIZE; j++)
  1048.     gtk_preview_draw_row (GTK_PREVIEW(deviceD->colors[i]), buffer, 
  1049.                   0, j, CELL_SIZE);
  1050.       gtk_widget_draw (deviceD->colors[i], NULL);
  1051.       gtk_widget_show (deviceD->colors[i]);
  1052.  
  1053.       /*  Set the tip to be the RGB value  */
  1054.       g_snprintf (ttbuf, sizeof (ttbuf), "[%3d,%3d,%3d]",
  1055.           buffer[j],
  1056.           buffer[j+1],
  1057.           buffer[j+2]);
  1058.  
  1059.       gimp_help_set_help_data (deviceD->colors[i], ttbuf, NULL);
  1060.  
  1061.       if (gimp_context_get_brush (device_info->context))
  1062.     {
  1063.       gimp_context_preview_update
  1064.         (GIMP_CONTEXT_PREVIEW (deviceD->brushes[i]), 
  1065.          gimp_context_get_brush (device_info->context));
  1066.       gtk_widget_show (deviceD->brushes[i]);
  1067.     }
  1068.  
  1069.       if (gimp_context_get_pattern (device_info->context))
  1070.     {
  1071.       gimp_context_preview_update
  1072.         (GIMP_CONTEXT_PREVIEW (deviceD->patterns[i]), 
  1073.          gimp_context_get_pattern (device_info->context));
  1074.       gtk_widget_show (deviceD->patterns[i]);
  1075.     }
  1076.  
  1077.       if (gimp_context_get_gradient (device_info->context))
  1078.     {
  1079.       gimp_context_preview_update
  1080.         (GIMP_CONTEXT_PREVIEW (deviceD->gradients[i]), 
  1081.          gimp_context_get_gradient (device_info->context));
  1082.       gtk_widget_show (deviceD->gradients[i]);
  1083.     }
  1084.     }
  1085. }
  1086.  
  1087. /*  dnd stuff  */
  1088.  
  1089. static ToolType
  1090. device_status_drag_tool (GtkWidget *widget,
  1091.              gpointer   data)
  1092. {
  1093.   DeviceInfo *device_info;
  1094.  
  1095.   device_info = device_info_get_by_id (GPOINTER_TO_UINT (data));
  1096.  
  1097.   if (device_info)
  1098.     {
  1099.       return gimp_context_get_tool (device_info->context);
  1100.     }
  1101.   else
  1102.     {
  1103.       return RECT_SELECT;
  1104.     }
  1105. }
  1106.  
  1107. static void
  1108. device_status_drop_tool (GtkWidget *widget,
  1109.              ToolType   tool,
  1110.              gpointer   data)
  1111. {
  1112.   DeviceInfo *device_info;
  1113.  
  1114.   device_info = device_info_get_by_id (GPOINTER_TO_UINT (data));
  1115.  
  1116.   if (device_info && device_info->is_present)
  1117.     {
  1118.       gimp_context_set_tool (device_info->context, tool);
  1119.     }
  1120. }
  1121.  
  1122. static void
  1123. device_status_drag_color (GtkWidget *widget,
  1124.               guchar    *r,
  1125.               guchar    *g,
  1126.               guchar    *b,
  1127.               gpointer   data)
  1128. {
  1129.   DeviceInfo *device_info;
  1130.  
  1131.   device_info = device_info_get_by_id (GPOINTER_TO_UINT (data));
  1132.  
  1133.   if (device_info)
  1134.     {
  1135.       gimp_context_get_foreground (device_info->context, r, g, b);
  1136.     }
  1137.   else
  1138.     {
  1139.       *r = *g = *b = 0;
  1140.     }
  1141. }
  1142.  
  1143. static void
  1144. device_status_drop_color (GtkWidget *widget,
  1145.               guchar     r,
  1146.               guchar     g,
  1147.               guchar     b,
  1148.               gpointer   data)
  1149. {
  1150.   DeviceInfo *device_info;
  1151.  
  1152.   device_info = device_info_get_by_id (GPOINTER_TO_UINT (data));
  1153.  
  1154.   if (device_info && device_info->is_present)
  1155.     {
  1156.       gimp_context_set_foreground (device_info->context, r, g, b);
  1157.     }
  1158. }
  1159.  
  1160. static void
  1161. device_status_drop_brush (GtkWidget *widget,
  1162.               GimpBrush *brush,
  1163.               gpointer   data)
  1164. {
  1165.   DeviceInfo *device_info;
  1166.  
  1167.   device_info = device_info_get_by_id (GPOINTER_TO_UINT (data));
  1168.  
  1169.   if (device_info && device_info->is_present)
  1170.     {
  1171.       gimp_context_set_brush (device_info->context, brush);
  1172.     }
  1173. }
  1174.  
  1175. static void
  1176. device_status_drop_pattern (GtkWidget *widget,
  1177.                 GPattern  *pattern,
  1178.                 gpointer   data)
  1179. {
  1180.   DeviceInfo *device_info;
  1181.   
  1182.   device_info = device_info_get_by_id (GPOINTER_TO_UINT (data));
  1183.  
  1184.   if (device_info && device_info->is_present)
  1185.     {
  1186.       gimp_context_set_pattern (device_info->context, pattern);
  1187.     }
  1188. }
  1189.  
  1190. static void
  1191. device_status_drop_gradient (GtkWidget  *widget,
  1192.                  gradient_t *gradient,
  1193.                  gpointer    data)
  1194. {
  1195.   DeviceInfo *device_info;
  1196.   
  1197.   device_info = device_info_get_by_id (GPOINTER_TO_UINT (data));
  1198.  
  1199.   if (device_info && device_info->is_present)
  1200.     {
  1201.       gimp_context_set_gradient (device_info->context, gradient);
  1202.     }
  1203. }
  1204.  
  1205. /*  context callbacks  */
  1206.  
  1207. static void
  1208. device_status_color_changed (GimpContext *context,
  1209.                  gint         r,
  1210.                  gint         g,
  1211.                  gint         b,
  1212.                  gpointer     data)
  1213. {
  1214.   DeviceInfo *device_info;
  1215.  
  1216.   device_info = device_info_get_by_id (GPOINTER_TO_UINT (data));
  1217.  
  1218.   device_status_update (device_info->device);
  1219. }
  1220.  
  1221. static void
  1222. device_status_data_changed (GimpContext *context,
  1223.                 gpointer     dummy,
  1224.                 gpointer     data)
  1225. {
  1226.   DeviceInfo *device_info;
  1227.  
  1228.   device_info = device_info_get_by_id (GPOINTER_TO_UINT (data));
  1229.  
  1230.   device_status_update (device_info->device);
  1231. }
  1232.  
  1233. static void
  1234. device_status_context_connect  (GimpContext *context,
  1235.                 guint32      deviceid)
  1236. {
  1237.   gtk_signal_connect (GTK_OBJECT (context), "foreground_changed",
  1238.               GTK_SIGNAL_FUNC (device_status_color_changed),
  1239.               (gpointer) deviceid);
  1240.   gtk_signal_connect (GTK_OBJECT (context), "tool_changed",
  1241.               GTK_SIGNAL_FUNC (device_status_data_changed),
  1242.               (gpointer) deviceid);
  1243.   gtk_signal_connect (GTK_OBJECT (context), "brush_changed",
  1244.               GTK_SIGNAL_FUNC (device_status_data_changed),
  1245.               (gpointer) deviceid);
  1246.   gtk_signal_connect (GTK_OBJECT (context), "pattern_changed",
  1247.               GTK_SIGNAL_FUNC (device_status_data_changed),
  1248.               (gpointer) deviceid);
  1249.   gtk_signal_connect (GTK_OBJECT (context), "gradient_changed",
  1250.               GTK_SIGNAL_FUNC (device_status_data_changed),
  1251.               (gpointer) deviceid);
  1252. }
  1253.