home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / common / csource.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-22  |  21.1 KB  |  777 lines

  1. /* CSource - GIMP Plugin to dump image data in RGB(A) format for C source
  2.  * Copyright (C) 1999 Tim Janik
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (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 Library General Public
  15.  * License along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  17.  *
  18.  * This plugin is heavily based on the header plugin by Spencer Kimball and
  19.  * Peter Mattis.
  20.  */
  21.  
  22. #include "config.h"
  23.  
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <stdio.h>
  27.  
  28. #include <gtk/gtk.h>
  29.  
  30. #include <libgimp/gimp.h>
  31. #include <libgimp/gimpui.h>
  32.  
  33. #include "libgimp/stdplugins-intl.h"
  34.  
  35.  
  36. #define DEFAULT_COMMENT "Created with The GIMP"
  37.  
  38. typedef struct
  39. {
  40.   gchar    *file_name;
  41.   gchar    *prefixed_name;
  42.   gchar    *comment;
  43.   gboolean  use_comment;
  44.   gboolean  glib_types;
  45.   gboolean  alpha;
  46.   gboolean  use_macros;
  47.   gboolean  use_rle;
  48.   gdouble   opacity;
  49. } Config;
  50.  
  51.  
  52. /* --- prototypes --- */
  53. static void    query        (void);
  54. static void    run        (gchar   *name,
  55.                  gint     nparams,
  56.                  GimpParam  *param,
  57.                  gint    *nreturn_vals,
  58.                  GimpParam    **return_vals);
  59.  
  60. static gint    save_image    (Config  *config,
  61.                  gint32   image_ID,
  62.                  gint32   drawable_ID);
  63. static gboolean    run_save_dialog    (Config  *config);
  64.  
  65.  
  66. /* --- variables --- */
  67. GimpPlugInInfo PLUG_IN_INFO =
  68. {
  69.   NULL,  /* init_proc  */
  70.   NULL,  /* quit_proc  */
  71.   query, /* query_proc */
  72.   run,   /* run_proc   */
  73. };
  74.  
  75. Config config = 
  76. {
  77.   NULL,         /* file_name */
  78.   "gimp_image", /* prefixed_name */
  79.   NULL,         /* comment */
  80.   FALSE,        /* use_comment */
  81.   TRUE,         /* glib_types */
  82.   FALSE,        /* alpha */
  83.   FALSE,        /* use_macros */
  84.   FALSE,        /* use_rle */
  85.   100.0,        /* opacity */
  86. };
  87.  
  88. /* --- implement main (), provided by libgimp --- */
  89. MAIN ()
  90.  
  91. /* --- functions --- */
  92. static void
  93. query (void)
  94. {
  95.   static GimpParamDef save_args[] =
  96.   {
  97.     { GIMP_PDB_INT32, "run_mode", "Interactive" },
  98.     { GIMP_PDB_IMAGE, "image", "Input image" },
  99.     { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" },
  100.     { GIMP_PDB_STRING, "filename", "The name of the file to save the image in" },
  101.     { GIMP_PDB_STRING, "raw_filename", "The name of the file to save the image in" }
  102.   };
  103.   static gint nsave_args = sizeof (save_args) / sizeof (save_args[0]);
  104.  
  105.   gimp_install_procedure ("file_csource_save",
  106.                           "Dump image data in RGB(A) format for C source",
  107.                           "CSource cannot be run non-interactively.",
  108.                           "Tim Janik",
  109.                           "Tim Janik",
  110.                           "1999",
  111.                           "<Save>/C-Source",
  112.               "RGB*",
  113.                           GIMP_PLUGIN,
  114.                           nsave_args, 0,
  115.                           save_args, NULL);
  116.   
  117.   gimp_register_save_handler ("file_csource_save",
  118.                   "c",
  119.                   "");
  120. }
  121.  
  122. static void
  123. run (gchar   *name,
  124.      gint     nparams,
  125.      GimpParam  *param,
  126.      gint    *nreturn_vals,
  127.      GimpParam **return_vals)
  128. {
  129.   static GimpParam values[2];
  130.   GimpRunModeType  run_mode;
  131.   GimpPDBStatusType   status = GIMP_PDB_SUCCESS;
  132.   GimpExportReturnType export = GIMP_EXPORT_CANCEL;
  133.   
  134.   run_mode = param[0].data.d_int32;
  135.   
  136.   *nreturn_vals = 1;
  137.   *return_vals  = values;
  138.   values[0].type          = GIMP_PDB_STATUS;
  139.   values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  140.  
  141.   if (run_mode == GIMP_RUN_INTERACTIVE &&
  142.       strcmp (name, "file_csource_save") == 0)
  143.     {
  144.       gint32 image_ID    = param[1].data.d_int32;
  145.       gint32 drawable_ID = param[2].data.d_int32;
  146.       GimpParasite *parasite;
  147.       gchar *x;
  148.       GimpImageType drawable_type = gimp_drawable_type (drawable_ID);
  149.  
  150.       gimp_get_data ("file_csource_save", &config);
  151.       config.prefixed_name = "gimp_image";
  152.       config.comment       = NULL;
  153.  
  154.       config.file_name = param[3].data.d_string;
  155.       config.alpha = (drawable_type == GIMP_RGBA_IMAGE ||
  156.               drawable_type == GIMP_GRAYA_IMAGE ||
  157.               drawable_type == GIMP_INDEXEDA_IMAGE);
  158.  
  159.       INIT_I18N_UI();
  160.  
  161.       parasite = gimp_image_parasite_find (image_ID, "gimp-comment");
  162.       if (parasite)
  163.     {
  164.       config.comment = g_strdup (parasite->data);
  165.       gimp_parasite_free (parasite);
  166.     }
  167.       x = config.comment;
  168.  
  169.       if (!config.comment)
  170.     config.comment = g_strdup (DEFAULT_COMMENT);     
  171.  
  172.       gimp_ui_init ("csource", FALSE);
  173.       export = gimp_export_image (&image_ID, &drawable_ID, "C Source", 
  174.                   (GIMP_EXPORT_CAN_HANDLE_RGB |
  175.                    GIMP_EXPORT_CAN_HANDLE_ALPHA ));
  176.       if (export == GIMP_EXPORT_CANCEL)
  177.     {
  178.       values[0].data.d_status = GIMP_PDB_CANCEL;
  179.       return;
  180.     }
  181.  
  182.       if (run_save_dialog (&config))
  183.     {
  184.       if (x != config.comment &&
  185.           !(x && config.comment && strcmp (x, config.comment) == 0))
  186.         {
  187.           if (!config.comment || !config.comment[0])
  188.         gimp_image_parasite_detach (image_ID, "gimp-comment");
  189.           else
  190.         {
  191.           parasite = gimp_parasite_new ("gimp-comment",
  192.                         GIMP_PARASITE_PERSISTENT,
  193.                         strlen (config.comment) + 1,
  194.                         config.comment);
  195.           gimp_image_parasite_attach (image_ID, parasite);
  196.           gimp_parasite_free (parasite);
  197.         }
  198.         }
  199.  
  200.       if (! save_image (&config, image_ID, drawable_ID))
  201.         {
  202.           status = GIMP_PDB_EXECUTION_ERROR;
  203.         }
  204.       else
  205.         {
  206.           gimp_set_data ("file_csource_save", &config, sizeof (config));
  207.         }
  208.     }
  209.       else
  210.     {
  211.       status = GIMP_PDB_CANCEL;
  212.     }
  213.  
  214.       if (export == GIMP_EXPORT_EXPORT)
  215.     gimp_image_delete (image_ID);
  216.     }
  217.   else
  218.     {
  219.       status = GIMP_PDB_CALLING_ERROR;
  220.     }
  221.  
  222.   values[0].data.d_status = status;
  223. }
  224.  
  225. static gboolean
  226. diff2_rgb (guint8 *ip)
  227. {
  228.   return ip[0] != ip[3] || ip[1] != ip[4] || ip[2] != ip[5];
  229. }
  230.  
  231. static gboolean
  232. diff2_rgba (guint8 *ip)
  233. {
  234.   return ip[0] != ip[4] || ip[1] != ip[5] || ip[2] != ip[6] || ip[3] != ip[7];
  235. }
  236.  
  237. static guint8 *
  238. rl_encode_rgbx (guint8 *bp,
  239.         guint8 *ip,
  240.         guint8 *limit,
  241.         guint   n_ch)
  242. {
  243.   gboolean (*diff2_pix) (guint8 *) = n_ch > 3 ? diff2_rgba : diff2_rgb;
  244.   guint8 *ilimit = limit - n_ch;
  245.  
  246.   while (ip < limit)
  247.     {
  248.       g_assert (ip < ilimit); /* paranoid */
  249.  
  250.       if (diff2_pix (ip))
  251.     {
  252.       guint8 *s_ip = ip;
  253.       guint l = 1;
  254.  
  255.       ip += n_ch;
  256.       while (l < 127 && ip < ilimit && diff2_pix (ip))
  257.         { ip += n_ch; l += 1; }
  258.       if (ip == ilimit && l < 127)
  259.             { ip += n_ch; l += 1; }
  260.       *(bp++) = l;
  261.       memcpy (bp, s_ip, l * n_ch);
  262.       bp += l * n_ch;
  263.     }
  264.       else
  265.     {
  266.       guint l = 2;
  267.  
  268.       ip += n_ch;
  269.       while (l < 127 && ip < ilimit && !diff2_pix (ip))
  270.             { ip += n_ch; l += 1; }
  271.       *(bp++) = l | 128;
  272.       memcpy (bp, ip, n_ch);
  273.       ip += n_ch;
  274.       bp += n_ch;
  275.     }
  276.       if (ip == ilimit)
  277.     {
  278.       *(bp++) = 1;
  279.       memcpy (bp, ip, n_ch);
  280.       ip += n_ch;
  281.       bp += n_ch;
  282.     }
  283.     }
  284.  
  285.   return bp;
  286. }
  287.  
  288. static inline void
  289. save_rle_decoder (FILE        *fp,
  290.           const gchar *macro_name,
  291.           const gchar *s_uint,
  292.           const gchar *s_uint_8,
  293.           guint        n_ch)
  294. {
  295.   fprintf (fp, "#define %s_RUN_LENGTH_DECODE(image_buf, rle_data, size, bpp) do \\\n",
  296.        macro_name);
  297.   fprintf (fp, "{ %s __bpp; %s *__ip; const %s *__il, *__rd; \\\n", s_uint, s_uint_8, s_uint_8);
  298.   fprintf (fp, "  __bpp = (bpp); __ip = (image_buf); __il = __ip + (size) * __bpp; \\\n");
  299.  
  300.   fprintf (fp, "  __rd = (rle_data); if (__bpp > 3) { /* RGBA */ \\\n");
  301.  
  302.   fprintf (fp, "    while (__ip < __il) { %s __l = *(__rd++); \\\n", s_uint);
  303.   fprintf (fp, "      if (__l & 128) { __l = __l - 128; \\\n");
  304.   fprintf (fp, "        do { memcpy (__ip, __rd, 4); __ip += 4; } while (--__l); __rd += 4; \\\n");
  305.   fprintf (fp, "      } else { __l *= 4; memcpy (__ip, __rd, __l); \\\n");
  306.   fprintf (fp, "               __ip += __l; __rd += __l; } } \\\n");
  307.  
  308.   fprintf (fp, "  } else { /* RGB */ \\\n");
  309.  
  310.   fprintf (fp, "    while (__ip < __il) { %s __l = *(__rd++); \\\n", s_uint);
  311.   fprintf (fp, "      if (__l & 128) { __l = __l - 128; \\\n");
  312.   fprintf (fp, "        do { memcpy (__ip, __rd, 3); __ip += 3; } while (--__l); __rd += 3; \\\n");
  313.   fprintf (fp, "      } else { __l *= 3; memcpy (__ip, __rd, __l); \\\n");
  314.   fprintf (fp, "               __ip += __l; __rd += __l; } } \\\n");
  315.  
  316.   fprintf (fp, "  } } while (0)\n");
  317. }
  318.  
  319. static inline guint
  320. save_uchar (FILE   *fp,
  321.         guint   c,
  322.         guint8  d,
  323.         Config *config)
  324. {
  325.   static guint8 pad = 0;
  326.  
  327.   if (c > 74)
  328.     {
  329.       if (!config->use_macros)
  330.     {
  331.       fprintf (fp, "\"\n  \"");
  332.       c = 3;
  333.     }
  334.       else
  335.     {
  336.       fprintf (fp, "\"\n \"");
  337.       c = 2;
  338.     }
  339.     }
  340.   if (d < 33 || d > 126)
  341.     {
  342.       fprintf (fp, "\\%o", d);
  343.       c += 1 + 1 + (d > 7) + (d > 63);
  344.       pad = d < 64;
  345.  
  346.       return c;
  347.     }
  348.   
  349.   if (d == '\\')
  350.     {
  351.       fputs ("\\\\", fp);
  352.       c += 2;
  353.     }
  354.   else if (d == '"')
  355.     {
  356.       fputs ("\\\"", fp);
  357.       c += 2;
  358.     }
  359.   else if (pad && d >= '0' && d <= '9')
  360.     {
  361.       fputs ("\"\"", fp);
  362.       fputc (d, fp);
  363.       c += 3;
  364.     }
  365.   else
  366.     {
  367.       fputc (d, fp);
  368.       c += 1;
  369.     }
  370.   pad = 0;
  371.   
  372.   return c;
  373. }
  374.  
  375. static gint
  376. save_image (Config *config,
  377.         gint32  image_ID,
  378.         gint32  drawable_ID)
  379. {
  380.   GimpDrawable *drawable         = gimp_drawable_get (drawable_ID);
  381.   GimpImageType drawable_type = gimp_drawable_type (drawable_ID);
  382.   GimpPixelRgn pixel_rgn;
  383.   gchar *s_uint_8, *s_uint_32, *s_uint, *s_char, *s_null;
  384.   FILE *fp;
  385.   guint c;
  386.   gchar *macro_name;
  387.   guint8 *img_buffer, *img_buffer_end;
  388.  
  389.   fp = fopen (config->file_name, "w");
  390.   if (!fp)
  391.     return FALSE;
  392.  
  393.   gimp_pixel_rgn_init (&pixel_rgn, drawable,
  394.                0, 0, drawable->width, drawable->height, FALSE, FALSE);
  395.  
  396.   if (1)
  397.     {
  398.       guint8 *data, *p;
  399.       gint x, y, pad, n_bytes, bpp;
  400.  
  401.       bpp = config->alpha ? 4 : 3;
  402.       n_bytes = drawable->width * drawable->height * bpp;
  403.       pad = drawable->width * drawable->bpp;
  404.       if (config->use_rle)
  405.     pad = MAX (pad, 130 + n_bytes / 127);
  406.       data = g_new (guint8, pad + n_bytes);
  407.       p = data + pad;
  408.       for (y = 0; y < drawable->height; y++)
  409.     {
  410.       gimp_pixel_rgn_get_row (&pixel_rgn, data, 0, y, drawable->width);
  411.       if (config->alpha)
  412.         for (x = 0; x < drawable->width; x++)
  413.           {
  414.         guint8 *d = data + x * drawable->bpp;
  415.         gdouble alpha = drawable_type == GIMP_RGBA_IMAGE ? d[3] : 0xff;
  416.         
  417.         alpha *= config->opacity / 100.0;
  418.         *(p++) = d[0];
  419.         *(p++) = d[1];
  420.         *(p++) = d[2];
  421.         *(p++) = alpha + 0.5;
  422.           }
  423.       else
  424.         for (x = 0; x < drawable->width; x++)
  425.           {
  426.         guint8 *d = data + x * drawable->bpp;
  427.         gdouble alpha = drawable_type == GIMP_RGBA_IMAGE ? d[3] : 0xff;
  428.         
  429.         alpha *= config->opacity / 25600.0;
  430.         *(p++) = 0.5 + alpha * (gdouble) d[0];
  431.         *(p++) = 0.5 + alpha * (gdouble) d[1];
  432.         *(p++) = 0.5 + alpha * (gdouble) d[2];
  433.           }
  434.     }
  435.       img_buffer = data + pad;
  436.       if (config->use_rle)
  437.     {
  438.       img_buffer_end = rl_encode_rgbx (data, img_buffer,
  439.                        img_buffer + n_bytes, bpp);
  440.       img_buffer = data;
  441.     }
  442.       else
  443.     img_buffer_end = img_buffer + n_bytes;
  444.     }
  445.  
  446.   if (!config->use_macros && config->glib_types)
  447.     {
  448.       s_uint_8 =  "guint8 ";
  449.       s_uint_32 = "guint32";
  450.       s_uint  =   "guint  ";
  451.       s_char =    "gchar  ";
  452.       s_null =    "NULL";
  453.     }
  454.   else if (!config->use_macros)
  455.     {
  456.       s_uint_8 =  "unsigned char";
  457.       s_uint_32 = "unsigned int ";
  458.       s_uint =    "unsigned int ";
  459.       s_char =    "char         ";
  460.       s_null =    "(char*) 0";
  461.     }
  462.   else if (config->use_macros && config->glib_types)
  463.     {
  464.       s_uint_8 =  "guint8";
  465.       s_uint_32 = "guint32";
  466.       s_uint  =   "guint";
  467.       s_char =    "gchar";
  468.       s_null =    "NULL";
  469.     }
  470.   else /* config->use_macros && !config->glib_types */
  471.     {
  472.       s_uint_8 =  "unsigned char";
  473.       s_uint_32 = "unsigned int";
  474.       s_uint =    "unsigned int";
  475.       s_char =    "char";
  476.       s_null =    "(char*) 0";
  477.     }
  478.   macro_name = g_strdup (config->prefixed_name);
  479.   g_strup (macro_name);
  480.   
  481.   fprintf (fp, "/* GIMP %s C-Source image dump %s(%s) */\n\n",
  482.        config->alpha ? "RGBA" : "RGB",
  483.        config->use_rle ? "1-byte-run-length-encoded " : "",
  484.        g_basename (config->file_name));
  485.  
  486.   if (config->use_rle && !config->use_macros)
  487.     save_rle_decoder (fp,
  488.               macro_name,
  489.               config->glib_types ? "guint" : "unsigned int",
  490.               config->glib_types ? "guint8" : "unsigned char",
  491.               config->alpha ? 4 : 3);
  492.  
  493.   if (!config->use_macros)
  494.     {
  495.       fprintf (fp, "static const struct {\n");
  496.       fprintf (fp, "  %s\t width;\n", s_uint);
  497.       fprintf (fp, "  %s\t height;\n", s_uint);
  498.       fprintf (fp, "  %s\t bytes_per_pixel; /* 3:RGB, 4:RGBA */ \n", s_uint);
  499.       if (config->use_comment)
  500.     fprintf (fp, "  %s\t*comment;\n", s_char);
  501.       fprintf (fp, "  %s\t %spixel_data[",
  502.            s_uint_8,
  503.            config->use_rle ? "rle_" : "");
  504.       if (config->use_rle)
  505.     fprintf (fp, "%u];\n", img_buffer_end - img_buffer);
  506.       else
  507.     fprintf (fp, "%u * %u * %u];\n",
  508.          drawable->width,
  509.          drawable->height,
  510.          config->alpha ? 4 : 3);
  511.       fprintf (fp, "} %s = {\n", config->prefixed_name);
  512.       fprintf (fp, "  %u, %u, %u,\n",
  513.            drawable->width,
  514.            drawable->height,
  515.            config->alpha ? 4 : 3);
  516.     }
  517.   else /* use macros */
  518.     {
  519.       fprintf (fp, "#define %s_WIDTH (%u)\n",
  520.            macro_name, drawable->width);
  521.       fprintf (fp, "#define %s_HEIGHT (%u)\n",
  522.            macro_name, drawable->height);
  523.       fprintf (fp, "#define %s_BYTES_PER_PIXEL (%u) /* 3:RGB, 4:RGBA */\n",
  524.            macro_name, config->alpha ? 4 : 3);
  525.     }
  526.   if (config->use_comment && !config->comment)
  527.     {
  528.       if (!config->use_macros)
  529.     fprintf (fp, "  %s,\n", s_null);
  530.       else /* use macros */
  531.     fprintf (fp, "#define %s_COMMENT (%s)\n", macro_name, s_null);
  532.     }
  533.   else if (config->use_comment)
  534.     {
  535.       gchar *p = config->comment - 1;
  536.       
  537.       if (config->use_macros)
  538.     fprintf (fp, "#define %s_COMMENT \\\n", macro_name);
  539.       fprintf (fp, "  \"");
  540.       while (*(++p))
  541.     if (*p == '\\')
  542.       fprintf (fp, "\\\\");
  543.     else if (*p == '"')
  544.       fprintf (fp, "\\\"");
  545.     else if (*p == '\n' && p[1])
  546.       fprintf (fp, "\\n\"%s\n  \"",
  547.            config->use_macros ? " \\" : "");
  548.     else if (*p == '\n')
  549.       fprintf (fp, "\\n");
  550.     else if (*p == '\r')
  551.       fprintf (fp, "\\r");
  552.     else if (*p == '\b')
  553.       fprintf (fp, "\\b");
  554.     else if (*p == '\f')
  555.       fprintf (fp, "\\f");
  556.     else if (*p >= 32 && *p <= 126)
  557.       fprintf (fp, "%c", *p);
  558.     else
  559.       fprintf (fp, "\\%03o", *p);
  560.       if (!config->use_macros)
  561.     fprintf (fp, "\",\n");
  562.       else /* use macros */
  563.     fprintf (fp, "\"\n");
  564.     }
  565.   if (config->use_macros)
  566.     {
  567.       fprintf (fp, "#define %s_%sPIXEL_DATA ((%s*) %s_%spixel_data)\n",
  568.            macro_name,
  569.            config->use_rle ? "RLE_" : "",
  570.            s_uint_8,
  571.            macro_name,
  572.            config->use_rle ? "rle_" : "");
  573.       if (config->use_rle)
  574.     save_rle_decoder (fp,
  575.               macro_name,
  576.               s_uint,
  577.               s_uint_8,
  578.               config->alpha ? 4 : 3);
  579.       fprintf (fp, "static const %s %s_%spixel_data[",
  580.            s_uint_8,
  581.            macro_name,
  582.            config->use_rle ? "rle_" : "");
  583.       if (config->use_rle)
  584.     fprintf (fp, "%u] =\n", img_buffer_end - img_buffer);
  585.       else
  586.     fprintf (fp, "%u * %u * %u] =\n",
  587.          drawable->width,
  588.          drawable->height,
  589.          config->alpha ? 4 : 3);
  590.       fprintf (fp, "(\"");
  591.       c = 2;
  592.     }
  593.   else
  594.     {
  595.       fprintf (fp, "  \"");
  596.       c = 3;
  597.     }
  598.   switch (drawable_type)
  599.     {
  600.     case GIMP_RGB_IMAGE:
  601.     case GIMP_RGBA_IMAGE:
  602.       do
  603.     c = save_uchar (fp, c, *(img_buffer++), config);
  604.       while (img_buffer < img_buffer_end);
  605.       break;
  606.     default:
  607.       g_warning ("unhandled drawable type (%d)", drawable_type);
  608.       return FALSE;
  609.     }
  610.   if (!config->use_macros)
  611.     fprintf (fp, "\",\n};\n\n");
  612.   else /* use macros */
  613.     fprintf (fp, "\");\n\n");
  614.   
  615.   fclose (fp);
  616.   
  617.   gimp_drawable_detach (drawable);
  618.   
  619.   return TRUE;
  620. }
  621.  
  622. static GtkWidget *prefixed_name;
  623. static GtkWidget *centry;
  624. static gboolean   do_save = FALSE;
  625.  
  626. static void
  627. save_dialog_ok_callback (GtkWidget *widget,
  628.              gpointer   data)
  629. {
  630.   do_save = TRUE;
  631.  
  632.   config.prefixed_name =
  633.     g_strdup (gtk_entry_get_text (GTK_ENTRY (prefixed_name)));
  634.   config.comment = g_strdup (gtk_entry_get_text (GTK_ENTRY (centry)));
  635.  
  636.   gtk_widget_destroy (GTK_WIDGET (data));
  637. }
  638.  
  639. static gboolean
  640. run_save_dialog    (Config *config)
  641. {
  642.   GtkWidget *dialog;
  643.   GtkWidget *vbox;
  644.   GtkWidget *table;
  645.   GtkWidget *toggle;
  646.   GtkObject *adj;
  647.   
  648.   dialog = gimp_dialog_new (_("Save as C-Source"), "csource",
  649.                 gimp_standard_help_func, "filters/csource.html",
  650.                 GTK_WIN_POS_MOUSE,
  651.                 FALSE, TRUE, FALSE,
  652.  
  653.                 _("OK"), save_dialog_ok_callback,
  654.                 NULL, NULL, NULL, TRUE, FALSE,
  655.                 _("Cancel"), gtk_widget_destroy,
  656.                 NULL, 1, NULL, FALSE, TRUE,
  657.  
  658.                 NULL);
  659.  
  660.   gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
  661.               GTK_SIGNAL_FUNC (gtk_main_quit),
  662.               NULL);
  663.  
  664.  
  665.   vbox = gtk_vbox_new (FALSE, 2);
  666.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
  667.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
  668.   gtk_widget_show (vbox);
  669.  
  670.   table = gtk_table_new (2, 2, FALSE);
  671.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  672.   gtk_table_set_row_spacings (GTK_TABLE (table), 4);
  673.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  674.   gtk_widget_show (table);
  675.  
  676.   /* Prefixed Name
  677.    */
  678.   prefixed_name = gtk_entry_new ();
  679.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  680.                  _("Prefixed Name:"), 1.0, 0.5,
  681.                  prefixed_name, 1, FALSE);
  682.   gtk_entry_set_text (GTK_ENTRY (prefixed_name),
  683.               config->prefixed_name ? config->prefixed_name : "");
  684.   
  685.   /* Comment Entry
  686.    */
  687.   centry = gtk_entry_new ();
  688.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  689.                  _("Comment:"), 1.0, 0.5,
  690.                  centry, 1, FALSE);
  691.   gtk_entry_set_text (GTK_ENTRY (centry),
  692.               config->comment ? config->comment : "");
  693.  
  694.   /* Use Comment
  695.    */
  696.   toggle = gtk_check_button_new_with_label (_("Save Comment to File"));
  697.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  698.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  699.                 config->use_comment);
  700.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  701.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  702.               &config->use_comment);
  703.   gtk_widget_show (toggle);
  704.  
  705.   /* GLib types
  706.    */
  707.   toggle = gtk_check_button_new_with_label (_("Use GLib Types (guint8*)"));
  708.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  709.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  710.                 config->glib_types);
  711.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  712.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  713.               &config->glib_types);
  714.   gtk_widget_show (toggle);
  715.  
  716.   /* Use Macros
  717.    */
  718.   toggle = gtk_check_button_new_with_label (_("Use Macros instead of Struct"));
  719.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  720.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  721.                 config->use_macros);
  722.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  723.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  724.               &config->use_macros);
  725.   gtk_widget_show (toggle);
  726.  
  727.   /* Use RLE
  728.    */
  729.   toggle = gtk_check_button_new_with_label (_("Use 1 Byte Run-Length-Encoding"));
  730.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  731.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  732.                 config->use_rle);
  733.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  734.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  735.               &config->use_rle);
  736.   gtk_widget_show (toggle);
  737.  
  738.   /* Alpha
  739.    */
  740.   toggle = gtk_check_button_new_with_label (_("Save Alpha Channel (RGBA/RGB)"));
  741.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  742.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  743.                 config->alpha);
  744.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  745.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  746.               &config->alpha);
  747.   gtk_widget_show (toggle);
  748.  
  749.   /* Max Alpha Value
  750.    */
  751.   table = gtk_table_new (1, 3, FALSE);
  752.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  753.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  754.   gtk_widget_show (table);
  755.  
  756.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  757.                   _("Opacity:"), 100, 0,
  758.                   config->opacity, 0, 100, 1, 10, 1,
  759.                   TRUE, 0, 0,
  760.                   FALSE, FALSE);
  761.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  762.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  763.               &config->opacity);
  764.  
  765.   gtk_widget_show (dialog);
  766.   
  767.   gtk_main ();
  768.   gdk_flush ();
  769.   
  770.   if (!config->prefixed_name || !config->prefixed_name[0])
  771.     config->prefixed_name = "tmp";
  772.   if (config->comment && !config->comment[0])
  773.     config->comment = NULL;
  774.  
  775.   return do_save;
  776. }
  777.