home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / libgimp / gimp.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-10  |  28.0 KB  |  1,166 lines

  1. /* LIBGIMP - The GIMP Library
  2.  * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
  3.  *
  4.  * gimp.c
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Library General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the
  18.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19.  * Boston, MA 02111-1307, USA.
  20.  */
  21.  
  22. #include "config.h"
  23.  
  24. #include <locale.h>
  25. #include <errno.h>
  26. #include <stdarg.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <sys/types.h>
  31.  
  32. #ifdef HAVE_SYS_TIME_H
  33. #include <sys/time.h>
  34. #endif
  35.  
  36. #ifdef HAVE_SYS_PARAM_H
  37. #include <sys/param.h>
  38. #endif
  39.  
  40. #ifdef HAVE_SYS_WAIT_H
  41. #include <sys/wait.h>
  42. #endif
  43.  
  44. #ifdef HAVE_UNISTD_H
  45. #include <unistd.h>
  46. #endif
  47.  
  48. #ifndef WAIT_ANY
  49. #define WAIT_ANY -1
  50. #endif
  51.  
  52. #include <glib.h>
  53.  
  54. #ifndef G_OS_WIN32
  55. #include "gimpsignal.h"
  56. #else
  57. #include <signal.h>
  58. #endif
  59.  
  60. #include "gimpenv.h"
  61.  
  62. #ifdef HAVE_IPC_H
  63. #include <sys/ipc.h>
  64. #endif
  65.  
  66. #ifdef HAVE_SHM_H
  67. #include <sys/shm.h>
  68. #endif
  69.  
  70. #ifdef HAVE_SYS_SELECT_H
  71. #include <sys/select.h>
  72. #endif
  73.  
  74. #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
  75. #  define STRICT
  76. #  include <windows.h>
  77. #  undef RGB
  78. #endif
  79. #ifdef __EMX__
  80. #  include <fcntl.h>
  81. #endif
  82.  
  83. #include "gimp.h"
  84. #include "gimpprotocol.h"
  85. #include "gimpwire.h"
  86.  
  87.  
  88. #define WRITE_BUFFER_SIZE  1024
  89.  
  90. void gimp_extension_process (guint        timeout);
  91. void gimp_extension_ack     (void);
  92. void gimp_read_expect_msg   (WireMessage *msg,
  93.                  gint         type);
  94.  
  95.  
  96. #ifndef G_OS_WIN32
  97. static void       gimp_plugin_sigfatal_handler (gint            sig_num);
  98. #endif
  99. static gboolean   gimp_plugin_io_error_handler (GIOChannel     *channel,
  100.                         GIOCondition    cond,
  101.                         gpointer        data);
  102.  
  103. static gboolean   gimp_write                   (GIOChannel     *channel,
  104.                         guint8         *buf,
  105.                         gulong          count);
  106. static gboolean   gimp_flush                   (GIOChannel     *channel);
  107. static void       gimp_loop                    (void);
  108. static void       gimp_config                  (GPConfig       *config);
  109. static void       gimp_proc_run                (GPProcRun      *proc_run);
  110. static void       gimp_temp_proc_run           (GPProcRun      *proc_run);
  111. static void       gimp_message_func            (const gchar    *log_domain,
  112.                         GLogLevelFlags  log_level,
  113.                         const gchar    *message,
  114.                         gpointer        data);
  115. static void       gimp_process_message         (WireMessage    *msg);
  116. static void       gimp_close                   (void);
  117.  
  118.  
  119. GIOChannel *_readchannel  = NULL;
  120. GIOChannel *_writechannel = NULL;
  121.  
  122. gint    _shm_ID   = -1;
  123. guchar *_shm_addr = NULL;
  124.  
  125. guint gimp_major_version = GIMP_MAJOR_VERSION;
  126. guint gimp_minor_version = GIMP_MINOR_VERSION;
  127. guint gimp_micro_version = GIMP_MICRO_VERSION;
  128.  
  129. #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
  130. static HANDLE shm_handle;
  131. #endif
  132.  
  133. static gdouble  _gamma_val;
  134. static gboolean _install_cmap;
  135. static gboolean _use_xshm;
  136. static guchar   _color_cube[4];
  137. static gint     _min_colors;
  138. static gint     _gdisp_ID = -1;
  139.  
  140. static gchar   *progname = NULL;
  141. static guint8   write_buffer[WRITE_BUFFER_SIZE];
  142. static guint    write_buffer_index = 0;
  143.  
  144. static GimpStackTraceMode stack_trace_mode = GIMP_STACK_TRACE_NEVER;
  145.  
  146. static GHashTable *temp_proc_ht = NULL;
  147.  
  148. #ifdef G_OS_WIN32
  149. static GimpPlugInInfo *PLUG_IN_INFO_PTR;
  150. #define PLUG_IN_INFO (*PLUG_IN_INFO_PTR)
  151. void
  152. set_gimp_PLUG_IN_INFO_PTR (GimpPlugInInfo *p)
  153. {
  154.   PLUG_IN_INFO_PTR = p;
  155. }
  156. #else
  157. #ifndef __EMX__
  158. extern GimpPlugInInfo PLUG_IN_INFO;
  159. #else
  160. static GimpPlugInInfo PLUG_IN_INFO;
  161. void set_gimp_PLUG_IN_INFO (const GimpPlugInInfo *p)
  162. {
  163.   PLUG_IN_INFO = *p;
  164. }
  165. #endif
  166. #endif
  167.  
  168.  
  169. int
  170. gimp_main (int   argc,
  171.        char *argv[])
  172. {
  173. #ifdef G_OS_WIN32
  174.   int i, j, k;
  175. #endif
  176.  
  177.   setlocale (LC_NUMERIC, "C");
  178.  
  179. #ifdef G_OS_WIN32
  180.   g_assert (PLUG_IN_INFO_PTR != NULL);
  181.  
  182.   /* Check for exe file name with spaces in the path having been split up
  183.    * by buggy NT C runtime, or something. I don't know why this happens
  184.    * on NT (including w2k), but not on w95/98.
  185.    */
  186.  
  187.   for (i = 1; i < argc; i++)
  188.     {
  189.       k = strlen (argv[i]);
  190.       if (k > 10)
  191.     if (g_strcasecmp (argv[i] + k - 4, ".exe") == 0)
  192.       {
  193.         /* Found the end of the executable name, most probably.
  194.          * Splice the parts of the name back together.
  195.          */
  196.         GString *s;
  197.  
  198.         s = g_string_new (argv[0]);
  199.         for (j = 1; j <= i; j++)
  200.           {
  201.         s = g_string_append_c (s, ' ');
  202.         s = g_string_append (s, argv[j]);
  203.           }
  204.         argv[0] = s->str;
  205.         /* Move rest of argv down */
  206.         for (j = 1; j < argc - i; j++)
  207.           argv[j] = argv[j + i];
  208.         argv[argc - i] = NULL;
  209.         argc -= i;
  210.         break;
  211.       }
  212.     }
  213. #endif
  214.  
  215.   if ((argc != 6) || (strcmp (argv[1], "-gimp") != 0))
  216.     {
  217.       g_printerr ("%s is a gimp plug-in and must be run by the gimp to be used\n", argv[0]);
  218.       return 1;
  219.     }
  220.  
  221.   progname = argv[0];
  222.  
  223.   g_set_prgname (g_basename (progname));
  224.  
  225.   stack_trace_mode = (GimpStackTraceMode) CLAMP (atoi (argv[5]),
  226.                          GIMP_STACK_TRACE_NEVER,
  227.                          GIMP_STACK_TRACE_ALWAYS);
  228.  
  229. #ifndef G_OS_WIN32
  230.   /* No use catching these on Win32, the user won't get any meaningful
  231.    * stack trace from glib anyhow. It's better to let Windows inform
  232.    * about the program error, and offer debugging if the plug-in
  233.    * has been built with MSVC, and the user has MSVC installed.
  234.    */
  235.   gimp_signal_private (SIGHUP,  gimp_plugin_sigfatal_handler, 0);
  236.   gimp_signal_private (SIGINT,  gimp_plugin_sigfatal_handler, 0);
  237.   gimp_signal_private (SIGQUIT, gimp_plugin_sigfatal_handler, 0);
  238.   gimp_signal_private (SIGBUS,  gimp_plugin_sigfatal_handler, 0);
  239.   gimp_signal_private (SIGSEGV, gimp_plugin_sigfatal_handler, 0);
  240.   gimp_signal_private (SIGTERM, gimp_plugin_sigfatal_handler, 0);
  241.   gimp_signal_private (SIGFPE,  gimp_plugin_sigfatal_handler, 0);
  242.  
  243.   /* Ignore SIGPIPE from crashing Gimp */
  244.   gimp_signal_private (SIGPIPE, SIG_IGN, 0);
  245.  
  246.   /* Restart syscalls interrupted by SIGCHLD */
  247.   gimp_signal_private (SIGCHLD, SIG_DFL, SA_RESTART);
  248. #endif
  249.  
  250.   _readchannel  = g_io_channel_unix_new (atoi (argv[2]));
  251.   _writechannel = g_io_channel_unix_new (atoi (argv[3]));
  252. #ifdef __EMX__
  253.   setmode (g_io_channel_unix_get_fd (_readchannel), O_BINARY);
  254.   setmode (g_io_channel_unix_get_fd (_writechannel), O_BINARY);
  255. #endif
  256.  
  257.   gp_init ();
  258.   wire_set_writer (gimp_write);
  259.   wire_set_flusher (gimp_flush);
  260.  
  261.   g_log_set_handler ("LibGimp",
  262.              G_LOG_LEVEL_MESSAGE,
  263.              gimp_message_func,
  264.              NULL);
  265.   g_log_set_handler (NULL,
  266.              G_LOG_LEVEL_MESSAGE,
  267.              gimp_message_func,
  268.              NULL);
  269.  
  270.   if (strcmp (argv[4], "-query") == 0)
  271.     {
  272.       if (PLUG_IN_INFO.query_proc)
  273.     (* PLUG_IN_INFO.query_proc) ();
  274.       gimp_close ();
  275.       return 0;
  276.     }
  277.  
  278.   temp_proc_ht = g_hash_table_new (g_str_hash, g_str_equal);
  279.  
  280.   g_io_add_watch (_readchannel,
  281.           G_IO_ERR | G_IO_HUP,
  282.           gimp_plugin_io_error_handler,
  283.           NULL);
  284.  
  285.   gimp_loop ();
  286.   return 0;
  287. }
  288.  
  289. static void
  290. gimp_close (void)
  291. {
  292.   if (PLUG_IN_INFO.quit_proc)
  293.     (* PLUG_IN_INFO.quit_proc) ();
  294.  
  295. #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
  296.   CloseHandle (shm_handle);
  297. #else
  298. #ifdef HAVE_SHM_H
  299.   if ((_shm_ID != -1) && _shm_addr)
  300.     shmdt ((char*) _shm_addr);
  301. #endif
  302. #endif
  303.  
  304.   gp_quit_write (_writechannel);
  305. }
  306.  
  307. void
  308. gimp_quit (void)
  309. {
  310.   gimp_close ();
  311.   exit (0);
  312. }
  313.  
  314.  
  315. gint32
  316. gimp_default_display (void)
  317. {
  318.   return _gdisp_ID;
  319. }
  320.  
  321. static void
  322. gimp_message_func (const gchar    *log_domain,
  323.            GLogLevelFlags  log_level,
  324.            const gchar    *message,
  325.            gpointer        data)
  326. {
  327.   gimp_message ((gchar *) message);
  328. }
  329.  
  330. void
  331. gimp_install_procedure (gchar        *name,
  332.             gchar        *blurb,
  333.             gchar        *help,
  334.             gchar        *author,
  335.             gchar        *copyright,
  336.             gchar        *date,
  337.             gchar        *menu_path,
  338.             gchar        *image_types,
  339.             gint          type,
  340.             gint          nparams,
  341.             gint          nreturn_vals,
  342.             GimpParamDef *params,
  343.             GimpParamDef *return_vals)
  344. {
  345.   GPProcInstall proc_install;
  346.  
  347.   proc_install.name         = name;
  348.   proc_install.blurb        = blurb;
  349.   proc_install.help         = help;
  350.   proc_install.author       = author;
  351.   proc_install.copyright    = copyright;
  352.   proc_install.date         = date;
  353.   proc_install.menu_path    = menu_path;
  354.   proc_install.image_types  = image_types;
  355.   proc_install.type         = type;
  356.   proc_install.nparams      = nparams;
  357.   proc_install.nreturn_vals = nreturn_vals;
  358.   proc_install.params       = (GPParamDef *) params;
  359.   proc_install.return_vals  = (GPParamDef *) return_vals;
  360.  
  361.   if (!gp_proc_install_write (_writechannel, &proc_install))
  362.     gimp_quit ();
  363. }
  364.  
  365. void
  366. gimp_install_temp_proc (gchar        *name,
  367.             gchar        *blurb,
  368.             gchar        *help,
  369.             gchar        *author,
  370.             gchar        *copyright,
  371.             gchar        *date,
  372.             gchar        *menu_path,
  373.             gchar        *image_types,
  374.             gint          type,
  375.             gint          nparams,
  376.             gint          nreturn_vals,
  377.             GimpParamDef *params,
  378.             GimpParamDef *return_vals,
  379.             GimpRunProc   run_proc)
  380. {
  381.   gimp_install_procedure (name,
  382.               blurb, help,
  383.               author, copyright, date,
  384.               menu_path,
  385.               image_types,
  386.               type,
  387.               nparams, nreturn_vals,
  388.               params, return_vals);
  389.  
  390.   /*  Insert the temp proc run function into the hash table  */
  391.   g_hash_table_insert (temp_proc_ht, g_strdup (name), (gpointer) run_proc);
  392. }
  393.  
  394. void
  395. gimp_uninstall_temp_proc (gchar *name)
  396. {
  397.   GPProcUninstall proc_uninstall;
  398.   gpointer hash_name;
  399.   gboolean found;
  400.   proc_uninstall.name = name;
  401.  
  402.   if (!gp_proc_uninstall_write (_writechannel, &proc_uninstall))
  403.     gimp_quit ();
  404.   
  405.   found = g_hash_table_lookup_extended (temp_proc_ht, name, &hash_name, NULL);
  406.   if (found)
  407.     {
  408.       g_hash_table_remove (temp_proc_ht, (gpointer) name);
  409.       g_free (hash_name);
  410.     }
  411. }
  412.  
  413. GimpParam *
  414. gimp_run_procedure (gchar *name,
  415.             gint  *nreturn_vals,
  416.             ...)
  417. {
  418.   GPProcRun       proc_run;
  419.   GPProcReturn   *proc_return;
  420.   WireMessage     msg;
  421.   GimpPDBArgType  param_type;
  422.   GimpParam      *return_vals;
  423.   va_list         args;
  424.   guchar         *color;
  425.   gint            i;
  426.  
  427.   proc_run.name = name;
  428.   proc_run.nparams = 0;
  429.   proc_run.params = NULL;
  430.  
  431.   va_start (args, nreturn_vals);
  432.   param_type = va_arg (args, GimpPDBArgType);
  433.  
  434.   while (param_type != GIMP_PDB_END)
  435.     {
  436.       switch (param_type)
  437.     {
  438.     case GIMP_PDB_INT32:
  439.         case GIMP_PDB_DISPLAY:
  440.         case GIMP_PDB_IMAGE:
  441.         case GIMP_PDB_LAYER:
  442.         case GIMP_PDB_CHANNEL:
  443.         case GIMP_PDB_DRAWABLE:
  444.         case GIMP_PDB_SELECTION:
  445.         case GIMP_PDB_BOUNDARY:
  446.         case GIMP_PDB_PATH:
  447.         case GIMP_PDB_STATUS:
  448.       (void) va_arg (args, gint);
  449.       break;
  450.     case GIMP_PDB_INT16:
  451.       (void) va_arg (args, gint);
  452.       break;
  453.     case GIMP_PDB_INT8:
  454.       (void) va_arg (args, gint);
  455.       break;
  456.         case GIMP_PDB_FLOAT:
  457.           (void) va_arg (args, gdouble);
  458.           break;
  459.         case GIMP_PDB_STRING:
  460.           (void) va_arg (args, gchar *);
  461.           break;
  462.         case GIMP_PDB_INT32ARRAY:
  463.           (void) va_arg (args, gint32 *);
  464.           break;
  465.         case GIMP_PDB_INT16ARRAY:
  466.           (void) va_arg (args, gint16 *);
  467.           break;
  468.         case GIMP_PDB_INT8ARRAY:
  469.           (void) va_arg (args, gint8 *);
  470.           break;
  471.         case GIMP_PDB_FLOATARRAY:
  472.           (void) va_arg (args, gdouble *);
  473.           break;
  474.         case GIMP_PDB_STRINGARRAY:
  475.           (void) va_arg (args, gchar **);
  476.           break;
  477.         case GIMP_PDB_COLOR:
  478.           (void) va_arg (args, guchar *);
  479.           break;
  480.         case GIMP_PDB_PARASITE:
  481.           (void) va_arg (args, GimpParasite *);
  482.           break;
  483.         case GIMP_PDB_REGION:
  484.           break;
  485.     case GIMP_PDB_END:
  486.       break;
  487.     }
  488.  
  489.       proc_run.nparams += 1;
  490.       param_type = va_arg (args, GimpPDBArgType);
  491.     }
  492.  
  493.   va_end (args);
  494.  
  495.   proc_run.params = g_new (GPParam, proc_run.nparams);
  496.  
  497.   va_start (args, nreturn_vals);
  498.  
  499.   for (i = 0; i < proc_run.nparams; i++)
  500.     {
  501.       proc_run.params[i].type = va_arg (args, GimpPDBArgType);
  502.  
  503.       switch (proc_run.params[i].type)
  504.     {
  505.     case GIMP_PDB_INT32:
  506.       proc_run.params[i].data.d_int32 = (gint32) va_arg (args, gint);
  507.       break;
  508.     case GIMP_PDB_INT16:
  509.       proc_run.params[i].data.d_int16 = (gint16) va_arg (args, gint);
  510.       break;
  511.     case GIMP_PDB_INT8:
  512.       proc_run.params[i].data.d_int8 = (gint8) va_arg (args, gint);
  513.       break;
  514.         case GIMP_PDB_FLOAT:
  515.           proc_run.params[i].data.d_float = (gdouble) va_arg (args, gdouble);
  516.           break;
  517.         case GIMP_PDB_STRING:
  518.           proc_run.params[i].data.d_string = va_arg (args, gchar *);
  519.           break;
  520.         case GIMP_PDB_INT32ARRAY:
  521.           proc_run.params[i].data.d_int32array = va_arg (args, gint32 *);
  522.           break;
  523.         case GIMP_PDB_INT16ARRAY:
  524.           proc_run.params[i].data.d_int16array = va_arg (args, gint16 *);
  525.           break;
  526.         case GIMP_PDB_INT8ARRAY:
  527.           proc_run.params[i].data.d_int8array = va_arg (args, gint8 *);
  528.           break;
  529.         case GIMP_PDB_FLOATARRAY:
  530.           proc_run.params[i].data.d_floatarray = va_arg (args, gdouble *);
  531.           break;
  532.         case GIMP_PDB_STRINGARRAY:
  533.           proc_run.params[i].data.d_stringarray = va_arg (args, gchar **);
  534.           break;
  535.         case GIMP_PDB_COLOR:
  536.       color = va_arg (args, guchar *);
  537.           proc_run.params[i].data.d_color.red   = color[0];
  538.           proc_run.params[i].data.d_color.green = color[1];
  539.           proc_run.params[i].data.d_color.blue  = color[2];
  540.           break;
  541.         case GIMP_PDB_REGION:
  542.           break;
  543.         case GIMP_PDB_DISPLAY:
  544.       proc_run.params[i].data.d_display = va_arg (args, gint32);
  545.           break;
  546.         case GIMP_PDB_IMAGE:
  547.       proc_run.params[i].data.d_image = va_arg (args, gint32);
  548.           break;
  549.         case GIMP_PDB_LAYER:
  550.       proc_run.params[i].data.d_layer = va_arg (args, gint32);
  551.           break;
  552.         case GIMP_PDB_CHANNEL:
  553.       proc_run.params[i].data.d_channel = va_arg (args, gint32);
  554.           break;
  555.         case GIMP_PDB_DRAWABLE:
  556.       proc_run.params[i].data.d_drawable = va_arg (args, gint32);
  557.           break;
  558.         case GIMP_PDB_SELECTION:
  559.       proc_run.params[i].data.d_selection = va_arg (args, gint32);
  560.           break;
  561.         case GIMP_PDB_BOUNDARY:
  562.       proc_run.params[i].data.d_boundary = va_arg (args, gint32);
  563.           break;
  564.         case GIMP_PDB_PATH:
  565.       proc_run.params[i].data.d_path = va_arg (args, gint32);
  566.           break;
  567.         case GIMP_PDB_PARASITE:
  568.       {
  569.         GimpParasite *parasite = va_arg (args, GimpParasite *);
  570.  
  571.         if (parasite == NULL)
  572.           {
  573.         proc_run.params[i].data.d_parasite.name = NULL;
  574.         proc_run.params[i].data.d_parasite.data = NULL;
  575.           }
  576.         else
  577.           {
  578.         proc_run.params[i].data.d_parasite.name  = parasite->name;
  579.         proc_run.params[i].data.d_parasite.flags = parasite->flags;
  580.         proc_run.params[i].data.d_parasite.size  = parasite->size;
  581.         proc_run.params[i].data.d_parasite.data  = parasite->data;
  582.           }
  583.       }
  584.       break;
  585.         case GIMP_PDB_STATUS:
  586.       proc_run.params[i].data.d_status = va_arg (args, gint32);
  587.           break;
  588.     case GIMP_PDB_END:
  589.       break;
  590.     }
  591.     }
  592.  
  593.   va_end (args);
  594.  
  595.   if (!gp_proc_run_write (_writechannel, &proc_run))
  596.     gimp_quit ();
  597.  
  598.   gimp_read_expect_msg (&msg, GP_PROC_RETURN);
  599.  
  600.   proc_return = msg.data;
  601.   *nreturn_vals = proc_return->nparams;
  602.   return_vals = (GimpParam*) proc_return->params;
  603.  
  604.   switch (return_vals[0].data.d_status)
  605.     {
  606.     case GIMP_PDB_EXECUTION_ERROR:
  607.       /*g_warning ("an execution error occured while trying to run: \"%s\"", name);*/
  608.       break;
  609.     case GIMP_PDB_CALLING_ERROR:
  610.       g_warning ("a calling error occured while trying to run: \"%s\"", name);
  611.       break;
  612.     default:
  613.       break;
  614.     }
  615.  
  616.   g_free (proc_run.params);
  617.   g_free (proc_return->name);
  618.   g_free (proc_return);
  619.  
  620.   return return_vals;
  621. }
  622.  
  623. void
  624. gimp_read_expect_msg (WireMessage *msg, 
  625.               gint         type)
  626. {
  627.   while (TRUE)
  628.     {
  629.       if (!wire_read_msg (_readchannel, msg))
  630.     gimp_quit ();
  631.       
  632.       if (msg->type != type)
  633.     {
  634.       if (msg->type == GP_TEMP_PROC_RUN || msg->type == GP_QUIT)
  635.         {
  636.           gimp_process_message (msg);
  637.           continue;
  638.         }
  639.       else
  640.         g_error ("unexpected message: %d\n", msg->type);
  641.     }
  642.       else
  643.     break;
  644.     }
  645. }
  646.  
  647.  
  648. GimpParam *
  649. gimp_run_procedure2 (gchar     *name,
  650.              gint      *nreturn_vals,
  651.              gint       nparams,
  652.              GimpParam *params)
  653. {
  654.   GPProcRun     proc_run;
  655.   GPProcReturn *proc_return;
  656.   WireMessage   msg;
  657.   GimpParam    *return_vals;
  658.  
  659.   proc_run.name    = name;
  660.   proc_run.nparams = nparams;
  661.   proc_run.params  = (GPParam *) params;
  662.  
  663.   if (!gp_proc_run_write (_writechannel, &proc_run))
  664.     gimp_quit ();
  665.  
  666.   gimp_read_expect_msg(&msg,GP_PROC_RETURN);
  667.   
  668.   proc_return = msg.data;
  669.   *nreturn_vals = proc_return->nparams;
  670.   return_vals = (GimpParam *) proc_return->params;
  671.  
  672.   switch (return_vals[0].data.d_status)
  673.     {
  674.     case GIMP_PDB_EXECUTION_ERROR:
  675.       /*g_warning ("an execution error occured while trying to run: \"%s\"", name);*/
  676.       break;
  677.     case GIMP_PDB_CALLING_ERROR:
  678.       g_warning ("a calling error occured while trying to run: \"%s\"", name);
  679.       break;
  680.     default:
  681.       break;
  682.     }
  683.  
  684.   g_free (proc_return->name);
  685.   g_free (proc_return);
  686.  
  687.   return return_vals;
  688. }
  689.  
  690. void
  691. gimp_destroy_params (GimpParam *params,
  692.              gint       nparams)
  693. {
  694.   extern void _gp_params_destroy (GPParam *params, gint nparams);
  695.  
  696.   _gp_params_destroy ((GPParam*) params, nparams);
  697. }
  698.  
  699. void
  700. gimp_destroy_paramdefs (GimpParamDef *paramdefs,
  701.             gint          nparams)
  702. {
  703.   while (nparams--)
  704.     {
  705.       g_free (paramdefs[nparams].name);
  706.       g_free (paramdefs[nparams].description);
  707.     }
  708.  
  709.   g_free (paramdefs);
  710. }
  711.  
  712. gdouble
  713. gimp_gamma (void)
  714. {
  715.   return _gamma_val;
  716. }
  717.  
  718. gboolean
  719. gimp_install_cmap (void)
  720. {
  721.   return _install_cmap;
  722. }
  723.  
  724. gboolean
  725. gimp_use_xshm (void)
  726. {
  727.   return _use_xshm;
  728. }
  729.  
  730. guchar *
  731. gimp_color_cube (void)
  732. {
  733.   return _color_cube;
  734. }
  735.  
  736. gint
  737. gimp_min_colors (void)
  738. {
  739.   return _min_colors;
  740. }
  741.  
  742. static void
  743. gimp_process_message (WireMessage *msg)
  744. {
  745.   switch (msg->type)
  746.     {
  747.     case GP_QUIT:
  748.       gimp_quit ();
  749.       break;
  750.     case GP_CONFIG:
  751.       gimp_config (msg->data);
  752.       break;
  753.     case GP_TILE_REQ:
  754.     case GP_TILE_ACK:
  755.     case GP_TILE_DATA:
  756.       g_warning ("unexpected tile message received (should not happen)\n");
  757.       break;
  758.     case GP_PROC_RUN:
  759.       g_warning ("unexpected proc run message received (should not happen)\n");
  760.       break;
  761.     case GP_PROC_RETURN:
  762.       g_warning ("unexpected proc return message received (should not happen)\n");
  763.       break;
  764.     case GP_TEMP_PROC_RUN:
  765.       gimp_temp_proc_run (msg->data);
  766.       break;
  767.     case GP_TEMP_PROC_RETURN:
  768.       g_warning ("unexpected temp proc return message received (should not happen)\n");
  769.       break;
  770.     case GP_PROC_INSTALL:
  771.       g_warning ("unexpected proc install message received (should not happen)\n");
  772.       break;
  773.     }
  774. }
  775.  
  776. static void 
  777. gimp_single_message (void)
  778. {
  779.   WireMessage msg;
  780.  
  781.   /* Run a temp function */
  782.   if (!wire_read_msg (_readchannel, &msg))
  783.     gimp_quit ();
  784.  
  785.   gimp_process_message (&msg);
  786.   
  787.   wire_destroy (&msg);
  788. }
  789.  
  790. void
  791. gimp_extension_process (guint timeout)
  792. {
  793. #ifndef G_OS_WIN32
  794.   fd_set readfds;
  795.   gint   select_val;
  796.   struct timeval  tv;
  797.   struct timeval *tvp;
  798.  
  799.   if (timeout)
  800.     {
  801.       tv.tv_sec = timeout / 1000;
  802.       tv.tv_usec = (timeout % 1000) * 1000;
  803.       tvp = &tv;
  804.     }
  805.   else
  806.     tvp = NULL;
  807.  
  808.   FD_ZERO (&readfds);
  809.   FD_SET (g_io_channel_unix_get_fd (_readchannel), &readfds);
  810.  
  811.   if ((select_val = select (FD_SETSIZE, &readfds, NULL, NULL, tvp)) > 0)
  812.     {
  813.       gimp_single_message ();
  814.     }
  815.   else if (select_val == -1)
  816.     {
  817.       perror ("gimp_process");
  818.       gimp_quit ();
  819.     }
  820. #else
  821.   /* Zero means infinite wait for us, but g_poll and
  822.    * g_io_channel_win32_poll use -1 to indicate
  823.    * infinite wait.
  824.    */
  825.   GPollFD pollfd;
  826.  
  827.   if (timeout == 0)
  828.     timeout = -1;
  829.  
  830.   g_io_channel_win32_make_pollfd (_readchannel, G_IO_IN, &pollfd);
  831.  
  832.   if (g_io_channel_win32_poll (&pollfd, 1, timeout) == 1)
  833.     gimp_single_message ();
  834. #endif
  835. }
  836.  
  837. void
  838. gimp_extension_ack (void)
  839. {
  840.   /*  Send an extension initialization acknowledgement  */
  841.   if (! gp_extension_ack_write (_writechannel))
  842.     gimp_quit ();
  843. }
  844.  
  845. void
  846. gimp_run_temp (void)
  847. {
  848.   gimp_single_message ();
  849. }
  850.  
  851. gchar *
  852. gimp_get_progname (void)
  853. {
  854.   return progname;
  855. }
  856.  
  857. #ifndef G_OS_WIN32
  858. static void
  859. gimp_plugin_sigfatal_handler (gint sig_num)
  860. {
  861.   switch (sig_num)
  862.     {
  863.     case SIGHUP:
  864.     case SIGINT:
  865.     case SIGQUIT:
  866.     case SIGABRT:
  867.     case SIGTERM:
  868.       g_printerr ("%s terminated: %s\n", progname, g_strsignal (sig_num));
  869.       break;
  870.  
  871.     case SIGBUS:
  872.     case SIGSEGV:
  873.     case SIGFPE:
  874.     case SIGPIPE:
  875.     default:
  876.       g_printerr ("%s: fatal error: %s\n", progname, g_strsignal (sig_num));
  877.       switch (stack_trace_mode)
  878.     {
  879.     case GIMP_STACK_TRACE_NEVER:
  880.       break;
  881.  
  882.     case GIMP_STACK_TRACE_QUERY:
  883.       {
  884.         sigset_t sigset;
  885.  
  886.         sigemptyset (&sigset);
  887.         sigprocmask (SIG_SETMASK, &sigset, NULL);
  888.         g_on_error_query (progname);
  889.       }
  890.       break;
  891.  
  892.     case GIMP_STACK_TRACE_ALWAYS:
  893.       {
  894.         sigset_t sigset;
  895.  
  896.         sigemptyset (&sigset);
  897.         sigprocmask (SIG_SETMASK, &sigset, NULL);
  898.         g_on_error_stack_trace (progname);
  899.       }
  900.       break;
  901.     }
  902.       break;
  903.     }
  904.  
  905.   gimp_quit ();
  906. }
  907. #endif
  908.  
  909. static gboolean
  910. gimp_plugin_io_error_handler (GIOChannel   *channel,
  911.                   GIOCondition  cond,
  912.                   gpointer      data)
  913. {
  914.   g_printerr ("%s: fatal error: GIMP crashed\n", progname);
  915.   gimp_quit ();
  916.  
  917.   /* never reached */
  918.   return TRUE;
  919. }
  920.  
  921. static gboolean
  922. gimp_write (GIOChannel *channel, 
  923.         guint8     *buf, 
  924.         gulong      count)
  925. {
  926.   gulong bytes;
  927.  
  928.   while (count > 0)
  929.     {
  930.       if ((write_buffer_index + count) >= WRITE_BUFFER_SIZE)
  931.     {
  932.       bytes = WRITE_BUFFER_SIZE - write_buffer_index;
  933.       memcpy (&write_buffer[write_buffer_index], buf, bytes);
  934.       write_buffer_index += bytes;
  935.       if (!wire_flush (channel))
  936.         return FALSE;
  937.     }
  938.       else
  939.     {
  940.       bytes = count;
  941.       memcpy (&write_buffer[write_buffer_index], buf, bytes);
  942.       write_buffer_index += bytes;
  943.     }
  944.  
  945.       buf += bytes;
  946.       count -= bytes;
  947.     }
  948.  
  949.   return TRUE;
  950. }
  951.  
  952. static gboolean
  953. gimp_flush (GIOChannel *channel)
  954. {
  955.   GIOError error;
  956.   guint count;
  957.   guint bytes;
  958.  
  959.   if (write_buffer_index > 0)
  960.     {
  961.       count = 0;
  962.       while (count != write_buffer_index)
  963.         {
  964.       do
  965.         {
  966.           bytes = 0;
  967.           error = g_io_channel_write (channel, &write_buffer[count],
  968.                       (write_buffer_index - count),
  969.                       &bytes);
  970.         }
  971.       while (error == G_IO_ERROR_AGAIN);
  972.  
  973.       if (error != G_IO_ERROR_NONE)
  974.         return FALSE;
  975.  
  976.           count += bytes;
  977.         }
  978.  
  979.       write_buffer_index = 0;
  980.     }
  981.  
  982.   return TRUE;
  983. }
  984.  
  985. static void
  986. gimp_loop (void)
  987. {
  988.   WireMessage msg;
  989.  
  990.   while (TRUE)
  991.     {
  992.       if (!wire_read_msg (_readchannel, &msg))
  993.         {
  994.       gimp_close ();
  995.           return;
  996.         }
  997.  
  998.       switch (msg.type)
  999.     {
  1000.     case GP_QUIT:
  1001.       gimp_close ();
  1002.       return;
  1003.     case GP_CONFIG:
  1004.       gimp_config (msg.data);
  1005.       break;
  1006.     case GP_TILE_REQ:
  1007.     case GP_TILE_ACK:
  1008.     case GP_TILE_DATA:
  1009.       g_warning ("unexpected tile message received (should not happen)\n");
  1010.       break;
  1011.     case GP_PROC_RUN:
  1012.       gimp_proc_run (msg.data);
  1013.       gimp_close ();
  1014.           return;
  1015.     case GP_PROC_RETURN:
  1016.       g_warning ("unexpected proc return message received (should not happen)\n");
  1017.       break;
  1018.     case GP_TEMP_PROC_RUN:
  1019.       g_warning ("unexpected temp proc run message received (should not happen\n");
  1020.       break;
  1021.     case GP_TEMP_PROC_RETURN:
  1022.       g_warning ("unexpected temp proc return message received (should not happen\n");
  1023.       break;
  1024.     case GP_PROC_INSTALL:
  1025.       g_warning ("unexpected proc install message received (should not happen)\n");
  1026.       break;
  1027.     }
  1028.  
  1029.       wire_destroy (&msg);
  1030.     }
  1031. }
  1032.  
  1033. static void
  1034. gimp_config (GPConfig *config)
  1035. {
  1036.   extern gint _gimp_tile_width;
  1037.   extern gint _gimp_tile_height;
  1038.  
  1039.   if (config->version < GP_VERSION)
  1040.     {
  1041.       g_message ("Could not execute Plug-In \"%s\"\n(%s)\n\n"
  1042.          "The GIMP is using an older version of the "
  1043.          "Plug-In protocol than this Plug-In.",
  1044.          g_basename (progname), progname);
  1045.       gimp_quit ();
  1046.     }
  1047.   else if (config->version > GP_VERSION)
  1048.     {
  1049.       g_message ("Could not execute Plug-In \"%s\"\n(%s)\n\n"
  1050.          "The GIMP is using an older version of the "
  1051.          "Plug-In protocol than this Plug-In.",
  1052.          g_basename (progname), progname);
  1053.       gimp_quit ();
  1054.     }
  1055.  
  1056.   _gimp_tile_width  = config->tile_width;
  1057.   _gimp_tile_height = config->tile_height;
  1058.   _shm_ID           = config->shm_ID;
  1059.   _gamma_val        = config->gamma;
  1060.   _install_cmap     = config->install_cmap;
  1061.   _color_cube[0]    = 6;  /*  These are the former default values  */
  1062.   _color_cube[1]    = 6;  /*  (for backward compatibility only)    */
  1063.   _color_cube[2]    = 4;
  1064.   _color_cube[3]    = 24;
  1065.   _use_xshm         = config->use_xshm;
  1066.   _min_colors       = config->min_colors;
  1067.   _gdisp_ID         = config->gdisp_ID;
  1068.  
  1069.   if (_shm_ID != -1)
  1070.     {
  1071. #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
  1072.       /*
  1073.        * Use Win32 shared memory mechanisms for
  1074.        * transfering tile data
  1075.        */
  1076.       gchar fileMapName[128];
  1077.       gint  tileByteSize = _gimp_tile_width * _gimp_tile_height * 4;
  1078.  
  1079.       /* From the id, derive the file map name */
  1080.       g_snprintf (fileMapName, sizeof (fileMapName), "GIMP%d.SHM", _shm_ID);
  1081.  
  1082.       /* Open the file mapping */
  1083.       shm_handle = OpenFileMapping (FILE_MAP_ALL_ACCESS,
  1084.                     0, fileMapName);
  1085.       if (shm_handle)
  1086.     {
  1087.       /* Map the shared memory into our address space for use */
  1088.       _shm_addr = (guchar *) MapViewOfFile (shm_handle,
  1089.                         FILE_MAP_ALL_ACCESS,
  1090.                         0, 0, tileByteSize);
  1091.  
  1092.       /* Verify that we mapped our view */
  1093.       if (!_shm_addr)
  1094.         {
  1095.           g_warning ("MapViewOfFile error: %d... disabling shared memory transport",
  1096.              GetLastError());
  1097.         }
  1098.     }
  1099.       else
  1100.     {
  1101.       g_warning ("OpenFileMapping error: %d... disabling shared memory transport",
  1102.              GetLastError());
  1103.     }
  1104. #else
  1105. #ifdef HAVE_SHM_H
  1106.       _shm_addr = (guchar*) shmat (_shm_ID, 0, 0);
  1107.  
  1108.       if (_shm_addr == (guchar*) -1)
  1109.     g_error ("could not attach to gimp shared memory segment\n");
  1110. #endif
  1111. #endif
  1112.     }
  1113. }
  1114.  
  1115. static void
  1116. gimp_proc_run (GPProcRun *proc_run)
  1117. {
  1118.   GPProcReturn proc_return;
  1119.   GimpParam *return_vals;
  1120.   gint nreturn_vals;
  1121.  
  1122.   if (PLUG_IN_INFO.run_proc)
  1123.     {
  1124.       (* PLUG_IN_INFO.run_proc) (proc_run->name,
  1125.                  proc_run->nparams,
  1126.                  (GimpParam*) proc_run->params,
  1127.                  &nreturn_vals,
  1128.                  &return_vals);
  1129.  
  1130.       proc_return.name = proc_run->name;
  1131.       proc_return.nparams = nreturn_vals;
  1132.       proc_return.params = (GPParam*) return_vals;
  1133.  
  1134.       if (!gp_proc_return_write (_writechannel, &proc_return))
  1135.     gimp_quit ();
  1136.     }
  1137. }
  1138.  
  1139. static void
  1140. gimp_temp_proc_run (GPProcRun *proc_run)
  1141. {
  1142.   GimpParam   *return_vals;
  1143.   gint         nreturn_vals;
  1144.   GimpRunProc  run_proc;
  1145.  
  1146.   run_proc = (GimpRunProc) g_hash_table_lookup (temp_proc_ht, 
  1147.                         (gpointer) proc_run->name);
  1148.  
  1149.   if (run_proc)
  1150.     {
  1151.       (* run_proc) (proc_run->name,
  1152.             proc_run->nparams,
  1153.             (GimpParam*) proc_run->params,
  1154.             &nreturn_vals,
  1155.             &return_vals);
  1156.  
  1157.       /* No longer a return message */
  1158. /*       proc_return.name = proc_run->name; */
  1159. /*       proc_return.nparams = nreturn_vals; */
  1160. /*       proc_return.params = (GPParam*) return_vals; */
  1161.  
  1162. /*       if (!gp_temp_proc_return_write (_writechannel, &proc_return)) */
  1163. /*     gimp_quit (); */
  1164.     }
  1165. }
  1166.