gimp.c 48 KB
Newer Older
Manish Singh's avatar
Manish Singh committed
1 2 3
/* LIBGIMP - The GIMP Library
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
 *
4 5
 * gimp.c
 *
Manish Singh's avatar
Manish Singh committed
6
 * This library is free software; you can redistribute it and/or
Marc Lehmann's avatar
Marc Lehmann committed
7
 * modify it under the terms of the GNU Lesser General Public
Manish Singh's avatar
Manish Singh committed
8 9 10 11 12 13 14 15
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
Marc Lehmann's avatar
Marc Lehmann committed
16
 * You should have received a copy of the GNU Lesser General Public
17 18 19
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Manish Singh's avatar
Manish Singh committed
20
 */
21

Elliot Lee's avatar
Elliot Lee committed
22 23 24 25 26 27 28 29
#include "config.h"

#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
30

Tor Lillqvist's avatar
Tor Lillqvist committed
31
#ifdef HAVE_SYS_TIME_H
Elliot Lee's avatar
Elliot Lee committed
32
#include <sys/time.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
33
#endif
34

Tor Lillqvist's avatar
Tor Lillqvist committed
35
#ifdef HAVE_SYS_PARAM_H
Elliot Lee's avatar
Elliot Lee committed
36
#include <sys/param.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
37
#endif
38

39 40 41
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
42

Tor Lillqvist's avatar
Tor Lillqvist committed
43
#ifdef HAVE_UNISTD_H
Elliot Lee's avatar
Elliot Lee committed
44
#include <unistd.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
45
#endif
46 47 48 49 50

#ifndef WAIT_ANY
#define WAIT_ANY -1
#endif

51
#include <glib-object.h>
52

Manish Singh's avatar
Manish Singh committed
53
#ifndef G_OS_WIN32
54
#include "libgimpbase/gimpsignal.h"
Manish Singh's avatar
Manish Singh committed
55 56 57
#else
#include <signal.h>
#endif
Tor Lillqvist's avatar
Tor Lillqvist committed
58

59 60 61 62 63 64
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif

#if defined(USE_SYSV_SHM)

65 66 67 68 69 70 71 72
#ifdef HAVE_IPC_H
#include <sys/ipc.h>
#endif

#ifdef HAVE_SHM_H
#include <sys/shm.h>
#endif

73 74 75 76
#elif defined(USE_POSIX_SHM)

#ifdef HAVE_UNISTD_H
#include <unistd.h>
Elliot Lee's avatar
Elliot Lee committed
77 78
#endif

79 80 81 82 83
#include <fcntl.h>
#include <sys/mman.h>

#endif /* USE_POSIX_SHM */

Manish Singh's avatar
Manish Singh committed
84
#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
Tor Lillqvist's avatar
Tor Lillqvist committed
85 86
#  define STRICT
#  include <windows.h>
87
#  undef RGB
88
#  define USE_WIN32_SHM 1
Tor Lillqvist's avatar
Tor Lillqvist committed
89
#endif
90

91 92 93
#include <libintl.h>
#include <locale.h>

Tor Lillqvist's avatar
Tor Lillqvist committed
94 95 96 97
#ifndef LIBGIMP_COMPILATION
#define LIBGIMP_COMPILATION
#endif

98 99
#include "libgimpbase/gimpbasetypes.h"

100
#include "libgimpbase/gimpbase-private.h"
101 102 103 104
#include "libgimpbase/gimpenv.h"
#include "libgimpbase/gimpprotocol.h"
#include "libgimpbase/gimpwire.h"

Elliot Lee's avatar
Elliot Lee committed
105
#include "gimp.h"
106
#include "gimpunitcache.h"
Elliot Lee's avatar
Elliot Lee committed
107

108

109 110 111 112
#define TILE_MAP_SIZE (_tile_width * _tile_height * 4)

#define ERRMSG_SHM_FAILED "Could not attach to gimp shared memory segment"

113
/* Maybe this should go in a public header if we add other things to it */
114 115
typedef enum
{
116 117 118 119 120 121 122 123
  GIMP_DEBUG_PID            = 1 << 0,
  GIMP_DEBUG_FATAL_WARNINGS = 1 << 1,
  GIMP_DEBUG_QUERY          = 1 << 2,
  GIMP_DEBUG_INIT           = 1 << 3,
  GIMP_DEBUG_RUN            = 1 << 4,
  GIMP_DEBUG_QUIT           = 1 << 5,

  GIMP_DEBUG_DEFAULT        = (GIMP_DEBUG_RUN | GIMP_DEBUG_FATAL_WARNINGS)
124
} GimpDebugFlag;
Elliot Lee's avatar
Elliot Lee committed
125 126 127

#define WRITE_BUFFER_SIZE  1024

128 129
void gimp_read_expect_msg   (WireMessage *msg,
			     gint         type);
130

Elliot Lee's avatar
Elliot Lee committed
131

132
static void       gimp_close                   (void);
133
static void       gimp_debug_stop              (void);
134 135 136 137
static void       gimp_message_func            (const gchar    *log_domain,
						GLogLevelFlags  log_level,
						const gchar    *message,
						gpointer        data);
138
#ifndef G_OS_WIN32
139
static void       gimp_plugin_sigfatal_handler (gint            sig_num);
140
#endif
141 142 143 144 145
static gboolean   gimp_plugin_io_error_handler (GIOChannel     *channel,
						GIOCondition    cond,
						gpointer        data);
static gboolean   gimp_write                   (GIOChannel     *channel,
						guint8         *buf,
146 147 148 149
						gulong          count,
                                                gpointer        user_data);
static gboolean   gimp_flush                   (GIOChannel     *channel,
                                                gpointer        user_data);
150
static void       gimp_loop                    (void);
151 152 153 154
static void       gimp_config                  (GPConfig       *config);
static void       gimp_proc_run                (GPProcRun      *proc_run);
static void       gimp_temp_proc_run           (GPProcRun      *proc_run);
static void       gimp_process_message         (WireMessage    *msg);
155 156 157 158
static void       gimp_single_message          (void);
static gboolean   gimp_extension_read          (GIOChannel     *channel,
                                                GIOCondition    condition,
                                                gpointer        data);
159 160


161
static GIOChannel *_readchannel  = NULL;
Tor Lillqvist's avatar
Tor Lillqvist committed
162 163
GIOChannel *_writechannel = NULL;

164 165 166
const guint gimp_major_version = GIMP_MAJOR_VERSION;
const guint gimp_minor_version = GIMP_MINOR_VERSION;
const guint gimp_micro_version = GIMP_MICRO_VERSION;
Tor Lillqvist's avatar
Tor Lillqvist committed
167

168
#ifdef USE_WIN32_SHM
Tor Lillqvist's avatar
Tor Lillqvist committed
169 170
static HANDLE shm_handle;
#endif
Manish Singh's avatar
Manish Singh committed
171

172 173 174 175 176 177 178
static gint           _tile_width        = -1;
static gint           _tile_height       = -1;
static gint           _shm_ID            = -1;
static guchar        *_shm_addr          = NULL;
static gdouble        _gamma_val         = 1.0;
static gboolean       _install_cmap      = FALSE;
static gboolean       _show_tool_tips    = TRUE;
179
static gboolean       _show_help_button  = TRUE;
180 181 182 183 184 185 186 187
static GimpCheckSize  _check_size        = GIMP_CHECK_SIZE_MEDIUM_CHECKS;
static GimpCheckType  _check_type        = GIMP_CHECK_TYPE_GRAY_CHECKS;
static gint           _min_colors        = 144;
static gint           _gdisp_ID          = -1;
static gchar         *_wm_class          = NULL;
static gchar         *_display_name      = NULL;
static gint           _monitor_number    = 0;
static const gchar   *progname           = NULL;
Elliot Lee's avatar
Elliot Lee committed
188

189 190
static guint8         write_buffer[WRITE_BUFFER_SIZE];
static guint          write_buffer_index = 0;
Elliot Lee's avatar
Elliot Lee committed
191

192 193
static GimpStackTraceMode stack_trace_mode = GIMP_STACK_TRACE_NEVER;

194
static GHashTable    *temp_proc_ht       = NULL;
Elliot Lee's avatar
Elliot Lee committed
195

196
static guint          gimp_debug_flags   = 0;
197

198 199 200 201 202 203 204 205 206 207
static const GDebugKey gimp_debug_keys[] =
{
  { "pid",            GIMP_DEBUG_PID            },
  { "fatal-warnings", GIMP_DEBUG_FATAL_WARNINGS },
  { "fw",             GIMP_DEBUG_FATAL_WARNINGS },
  { "query",          GIMP_DEBUG_QUERY          },
  { "init",           GIMP_DEBUG_INIT           },
  { "run",            GIMP_DEBUG_RUN            },
  { "quit",           GIMP_DEBUG_QUIT           },
  { "on",             GIMP_DEBUG_DEFAULT        }
208 209 210
};


211
static GimpPlugInInfo PLUG_IN_INFO;
Elliot Lee's avatar
Elliot Lee committed
212 213


214 215 216 217 218
/**
 * gimp_main:
 * @info: the PLUG_IN_INFO structure
 * @argc: the number of arguments
 * @argv: the arguments
219
 *
220 221
 * The main procedure that must be called with the PLUG_IN_INFO structure
 * and the 'argc' and 'argv' that are passed to "main".
222 223
 *
 * Return value:
224 225
 **/
gint
226
gimp_main (const GimpPlugInInfo *info,
227 228
           gint                  argc,
	   gchar                *argv[])
Elliot Lee's avatar
Elliot Lee committed
229
{
230 231 232
  gchar       *basename;
  const gchar *env_string;
  gchar       *debug_string;
233

234
#ifdef G_OS_WIN32
235
  gint i, j, k;
236 237 238 239 240 241 242 243 244

  /* Check for exe file name with spaces in the path having been split up
   * by buggy NT C runtime, or something. I don't know why this happens
   * on NT (including w2k), but not on w95/98.
   */

  for (i = 1; i < argc; i++)
    {
      k = strlen (argv[i]);
245

246
      if (k > 10)
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
	{
	  if (g_ascii_strcasecmp (argv[i] + k - 4, ".exe") == 0)
	    {
	      /* Found the end of the executable name, most probably.
	       * Splice the parts of the name back together.
	       */
	      GString *s;

	      s = g_string_new (argv[0]);

	      for (j = 1; j <= i; j++)
		{
		  s = g_string_append_c (s, ' ');
		  s = g_string_append (s, argv[j]);
		}

	      argv[0] = s->str;

	      /* Move rest of argv down */
	      for (j = 1; j < argc - i; j++)
		argv[j] = argv[j + i];

	      argv[argc - i] = NULL;
	      argc -= i;

	      break;
273
	  }
274
       }
275
    }
Tor Lillqvist's avatar
Tor Lillqvist committed
276 277
#endif

278 279 280 281
  g_assert (info != NULL);

  PLUG_IN_INFO = *info;

282
  if ((argc != 6) || (strcmp (argv[1], "-gimp") != 0))
Elliot Lee's avatar
Elliot Lee committed
283
    {
284 285
      g_printerr ("%s is a GIMP plug-in and must be run by GIMP to be used\n",
                  argv[0]);
Elliot Lee's avatar
Elliot Lee committed
286 287 288 289 290
      return 1;
    }

  progname = argv[0];

291 292 293 294
  basename = g_path_get_basename (progname);

  g_set_prgname (basename);

295 296 297 298 299 300 301 302 303 304 305 306 307
  env_string = g_getenv ("GIMP_PLUGIN_DEBUG");

  if (env_string)
    {
      debug_string = strchr (env_string, ',');

      if (debug_string)
        {
          gint len = debug_string - env_string;

	  if ((strlen (basename) == len) &&
              (strncmp (basename, env_string, len) == 0))
            {
308 309 310 311
              gimp_debug_flags =
                g_parse_debug_string (debug_string + 1,
                                      gimp_debug_keys,
                                      G_N_ELEMENTS (gimp_debug_keys));
312 313 314 315 316 317 318 319
            }
        }
      else if (strcmp (env_string, basename) == 0)
        {
          gimp_debug_flags = GIMP_DEBUG_DEFAULT;
        }
    }

320
  g_free (basename);
321

322 323 324 325
  stack_trace_mode = (GimpStackTraceMode) CLAMP (atoi (argv[5]),
						 GIMP_STACK_TRACE_NEVER,
						 GIMP_STACK_TRACE_ALWAYS);

326
#ifndef G_OS_WIN32
327 328 329 330 331
  /* No use catching these on Win32, the user won't get any meaningful
   * stack trace from glib anyhow. It's better to let Windows inform
   * about the program error, and offer debugging if the plug-in
   * has been built with MSVC, and the user has MSVC installed.
   */
332 333 334 335 336 337 338 339 340 341 342 343
  gimp_signal_private (SIGHUP,  gimp_plugin_sigfatal_handler, 0);
  gimp_signal_private (SIGINT,  gimp_plugin_sigfatal_handler, 0);
  gimp_signal_private (SIGQUIT, gimp_plugin_sigfatal_handler, 0);
  gimp_signal_private (SIGBUS,  gimp_plugin_sigfatal_handler, 0);
  gimp_signal_private (SIGSEGV, gimp_plugin_sigfatal_handler, 0);
  gimp_signal_private (SIGTERM, gimp_plugin_sigfatal_handler, 0);
  gimp_signal_private (SIGFPE,  gimp_plugin_sigfatal_handler, 0);

  /* Ignore SIGPIPE from crashing Gimp */
  gimp_signal_private (SIGPIPE, SIG_IGN, 0);

  /* Restart syscalls interrupted by SIGCHLD */
344
  gimp_signal_private (SIGCHLD, SIG_DFL, SA_RESTART);
345
#endif
Elliot Lee's avatar
Elliot Lee committed
346

347
  _readchannel  = g_io_channel_unix_new (atoi (argv[2]));
Tor Lillqvist's avatar
Tor Lillqvist committed
348
  _writechannel = g_io_channel_unix_new (atoi (argv[3]));
Elliot Lee's avatar
Elliot Lee committed
349

350 351 352
  g_io_channel_set_encoding (_readchannel, NULL, NULL);
  g_io_channel_set_encoding (_writechannel, NULL, NULL);

353 354 355 356 357 358
  g_io_channel_set_buffered (_readchannel, FALSE);
  g_io_channel_set_buffered (_writechannel, FALSE);

  g_io_channel_set_close_on_unref (_readchannel, TRUE);
  g_io_channel_set_close_on_unref (_writechannel, TRUE);

Elliot Lee's avatar
Elliot Lee committed
359 360 361 362
  gp_init ();
  wire_set_writer (gimp_write);
  wire_set_flusher (gimp_flush);

363
  g_type_init ();
364
  gimp_enums_init ();
365

366 367 368 369 370
  /*  initialize units  */
  {
    GimpUnitVTable vtable;

    vtable.unit_get_number_of_units = _gimp_unit_cache_get_number_of_units;
371 372
    vtable.unit_get_number_of_built_in_units =
      _gimp_unit_cache_get_number_of_built_in_units;
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
    vtable.unit_new                 = _gimp_unit_cache_new;
    vtable.unit_get_deletion_flag   = _gimp_unit_cache_get_deletion_flag;
    vtable.unit_set_deletion_flag   = _gimp_unit_cache_set_deletion_flag;
    vtable.unit_get_factor          = _gimp_unit_cache_get_factor;
    vtable.unit_get_digits          = _gimp_unit_cache_get_digits;
    vtable.unit_get_identifier      = _gimp_unit_cache_get_identifier;
    vtable.unit_get_symbol          = _gimp_unit_cache_get_symbol;
    vtable.unit_get_abbreviation    = _gimp_unit_cache_get_abbreviation;
    vtable.unit_get_singular        = _gimp_unit_cache_get_singular;
    vtable.unit_get_plural          = _gimp_unit_cache_get_plural;

    gimp_base_init (&vtable);
  }


388 389 390 391 392 393 394 395 396 397 398
  /* initialize i18n support */

  setlocale (LC_ALL, "");

  bindtextdomain (GETTEXT_PACKAGE"-libgimp", gimp_locale_directory ());
#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
  bind_textdomain_codeset (GETTEXT_PACKAGE"-libgimp", "UTF-8");
#endif


  /* set handler both for the "LibGimp" and "" domains */
399

400
  g_log_set_handler (G_LOG_DOMAIN,
401 402 403
		     G_LOG_LEVEL_MESSAGE,
		     gimp_message_func,
		     NULL);
404
  g_log_set_handler (NULL,
405 406 407 408
		     G_LOG_LEVEL_MESSAGE,
		     gimp_message_func,
		     NULL);

409 410 411 412 413 414 415 416 417
  if (gimp_debug_flags & GIMP_DEBUG_FATAL_WARNINGS)
    {
      GLogLevelFlags fatal_mask;

      fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
      fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
      g_log_set_always_fatal (fatal_mask);
    }

418
  if (strcmp (argv[4], "-query") == 0)
Elliot Lee's avatar
Elliot Lee committed
419
    {
420
      if (PLUG_IN_INFO.init_proc)
421
        gp_has_init_write (_writechannel, NULL);
422 423 424 425

      if (gimp_debug_flags & GIMP_DEBUG_QUERY)
        gimp_debug_stop ();

Elliot Lee's avatar
Elliot Lee committed
426 427
      if (PLUG_IN_INFO.query_proc)
	(* PLUG_IN_INFO.query_proc) ();
428

Marc Lehmann's avatar
Marc Lehmann committed
429
      gimp_close ();
430 431

      return EXIT_SUCCESS;
Elliot Lee's avatar
Elliot Lee committed
432 433
    }

434 435
  if (strcmp (argv[4], "-init") == 0)
    {
436 437 438
      if (gimp_debug_flags & GIMP_DEBUG_INIT)
        gimp_debug_stop ();

439 440
      if (PLUG_IN_INFO.init_proc)
	(* PLUG_IN_INFO.init_proc) ();
441

442
      gimp_close ();
443 444

      return EXIT_SUCCESS;
445 446
    }

447 448 449
  if (gimp_debug_flags & GIMP_DEBUG_RUN)
    gimp_debug_stop ();
  else if (gimp_debug_flags & GIMP_DEBUG_PID)
450
    g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Here I am!");
451

452
  temp_proc_ht = g_hash_table_new (g_str_hash, g_str_equal);
Elliot Lee's avatar
Elliot Lee committed
453

454 455 456 457 458
  g_io_add_watch (_readchannel,
		  G_IO_ERR | G_IO_HUP,
		  gimp_plugin_io_error_handler,
		  NULL);

Elliot Lee's avatar
Elliot Lee committed
459
  gimp_loop ();
460 461

  return EXIT_SUCCESS;
Elliot Lee's avatar
Elliot Lee committed
462 463
}

464 465
/**
 * gimp_quit:
466
 *
467 468 469
 * Forcefully causes the gimp library to exit and close down its
 * connection to main gimp application. This function never returns.
 **/
Marc Lehmann's avatar
Marc Lehmann committed
470
void
471
gimp_quit (void)
Marc Lehmann's avatar
Marc Lehmann committed
472 473
{
  gimp_close ();
474 475

  exit (EXIT_SUCCESS);
Elliot Lee's avatar
Elliot Lee committed
476 477
}

478 479 480 481 482 483 484 485 486
/**
 * gimp_install_procedure:
 * @name:          the procedure's name.
 * @blurb:         a short text describing what the procedure does.
 * @help:          the help text for the procedure (usually considerably
 *                 longer than @blurb).
 * @author:        the procedure's author(s).
 * @copyright:     the procedure's copyright.
 * @date:          the date the procedure was added.
487 488
 * @menu_label:    the label to use for the procedure's menu entry,
 *                 or #NULL if the procedure has no menu entry.
489 490 491 492 493 494
 * @image_types:   the drawable types the procedure can handle.
 * @type:          the type of the procedure.
 * @n_params:      the number of parameters the procedure takes.
 * @n_return_vals: the number of return values the procedure returns.
 * @params:        the procedure's parameters.
 * @return_vals:   the procedure's return values.
495
 *
496 497 498 499 500 501 502 503 504 505 506 507 508
 * Installs a new procedure with the PDB (procedural database).
 *
 * Call this function from within your Plug-In's query() function for
 * each procedure your Plug-In implements.
 *
 * The @name parameter is mandatory and should be unique, or it will
 * overwrite an already existing procedure (overwrite procedures only
 * if you know what you're doing).
 *
 * The @blurb, @help, @author, @copyright and @date parameters are
 * optional but then you shouldn't write procedures without proper
 * documentation, should you.
 *
509 510 511 512 513 514 515
 * @menu_label defines the label that should be used for the
 * procedure's menu entry (use #NULL if the procedure shouldn't have a
 * menu entry).  The position where to register in the menu hierarchy
 * is choosen using gimp_plugin_menu_register().  This function also
 * still accepts the old (pre-2.2) way of registering a menu entry and
 * takes a string in the form "&lt;Domain&gt;/Path/To/My/Menu"
 * (e.g. "&lt;Image&gt;/Filters/Render/Useless").
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
 *
 * @type must be one of #GIMP_PLUGIN or #GIMP_EXTENSION. Note that
 * temporary procedures must be installed using
 * gimp_install_temp_proc().
 *
 * NOTE: Unlike the GIMP 1.2 API, #GIMP_EXTENSION no longer means
 * that the procedure's menu prefix is &lt;Toolbox&gt;, but that
 * it will install temporary procedures. Therefore, the GIMP core
 * will wait until the #GIMP_EXTENSION procedure has called
 * gimp_extension_ack(), which means that the procedure has done
 * its initialization, installed its temporary procedures and is
 * ready to run.
 *
 * <emphasis>Not calling gimp_extension_ack() from a #GIMP_EXTENSION
 * procedure will cause th GIMP core to lock up.</emphasis>
 *
 * Additionally, a #GIMP_EXTENSION procedure with no parameters
 * (@n_params == 0 and @params == #NULL) is an "automatic" extension
 * that will be automatically started on each GIMP startup.
 **/
Elliot Lee's avatar
Elliot Lee committed
536
void
537 538 539 540 541 542
gimp_install_procedure (const gchar        *name,
			const gchar        *blurb,
			const gchar        *help,
			const gchar        *author,
			const gchar        *copyright,
			const gchar        *date,
543
			const gchar        *menu_label,
544 545 546 547 548 549
			const gchar        *image_types,
			GimpPDBProcType     type,
			gint                n_params,
			gint                n_return_vals,
			const GimpParamDef *params,
			const GimpParamDef *return_vals)
Elliot Lee's avatar
Elliot Lee committed
550 551 552
{
  GPProcInstall proc_install;

553 554 555 556 557 558 559 560 561 562 563 564 565
  g_return_if_fail (name != NULL);
  g_return_if_fail (type != GIMP_INTERNAL);
  g_return_if_fail ((n_params == 0 && params == NULL) ||
                    (n_params > 0  && params != NULL));
  g_return_if_fail ((n_return_vals == 0 && return_vals == NULL) ||
                    (n_return_vals > 0  && return_vals != NULL));

  proc_install.name         = (gchar *) name;
  proc_install.blurb        = (gchar *) blurb;
  proc_install.help         = (gchar *) help;
  proc_install.author       = (gchar *) author;
  proc_install.copyright    = (gchar *) copyright;
  proc_install.date         = (gchar *) date;
566
  proc_install.menu_path    = (gchar *) menu_label;
567
  proc_install.image_types  = (gchar *) image_types;
568
  proc_install.type         = type;
569 570
  proc_install.nparams      = n_params;
  proc_install.nreturn_vals = n_return_vals;
571 572
  proc_install.params       = (GPParamDef *) params;
  proc_install.return_vals  = (GPParamDef *) return_vals;
Elliot Lee's avatar
Elliot Lee committed
573

574
  if (! gp_proc_install_write (_writechannel, &proc_install, NULL))
Elliot Lee's avatar
Elliot Lee committed
575 576 577
    gimp_quit ();
}

578 579 580 581 582 583 584 585 586
/**
 * gimp_install_temp_proc:
 * @name:          the procedure's name.
 * @blurb:         a short text describing what the procedure does.
 * @help:          the help text for the procedure (usually considerably
 *                 longer than @blurb).
 * @author:        the procedure's author(s).
 * @copyright:     the procedure's copyright.
 * @date:          the date the procedure was added.
587
 * @menu_label:    the procedure's menu label, or #NULL if the procedure has
588 589 590 591 592 593 594 595
 *                 no menu entry.
 * @image_types:   the drawable types the procedure can handle.
 * @type:          the type of the procedure.
 * @n_params:      the number of parameters the procedure takes.
 * @n_return_vals: the number of return values the procedure returns.
 * @params:        the procedure's parameters.
 * @return_vals:   the procedure's return values.
 * @run_proc:      the function to call for executing the procedure.
596
 *
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
 * Installs a new temporary procedure with the PDB (procedural database).
 *
 * A temporary procedure is a procedure which is only available while
 * one of your Plug-In's "real" procedures is running.
 *
 * See gimp_install_procedure() for most details.
 *
 * @type <emphasis>must</emphasis> be #GIMP_TEMPORARY or the function
 * will fail.
 *
 * @run_proc is the function which will be called to execute the
 * procedure.
 *
 * NOTE: Normally, Plug-In communication is triggered by the Plug-In
 * and the GIMP core only responds to the Plug-In's requests. You must
 * explicitely enable receiving of temporary procedure run requests
 * using either gimp_extension_enable() or
 * gimp_extension_process(). See this functions' documentation for
 * details.
 **/
Elliot Lee's avatar
Elliot Lee committed
617
void
618 619 620 621 622 623
gimp_install_temp_proc (const gchar        *name,
			const gchar        *blurb,
			const gchar        *help,
			const gchar        *author,
			const gchar        *copyright,
			const gchar        *date,
624
			const gchar        *menu_label,
625 626 627 628 629 630 631
			const gchar        *image_types,
			GimpPDBProcType     type,
			gint                n_params,
			gint                n_return_vals,
			const GimpParamDef *params,
			const GimpParamDef *return_vals,
			GimpRunProc         run_proc)
Elliot Lee's avatar
Elliot Lee committed
632
{
633 634 635 636 637 638 639 640
  g_return_if_fail (name != NULL);
  g_return_if_fail ((n_params == 0 && params == NULL) ||
                    (n_params > 0  && params != NULL));
  g_return_if_fail ((n_return_vals == 0 && return_vals == NULL) ||
                    (n_return_vals > 0  && return_vals != NULL));
  g_return_if_fail (type == GIMP_TEMPORARY);
  g_return_if_fail (run_proc != NULL);

641 642 643
  gimp_install_procedure (name,
			  blurb, help,
			  author, copyright, date,
644
			  menu_label,
645 646
			  image_types,
			  type,
647
			  n_params, n_return_vals,
648
			  params, return_vals);
Elliot Lee's avatar
Elliot Lee committed
649 650

  /*  Insert the temp proc run function into the hash table  */
651
  g_hash_table_insert (temp_proc_ht, g_strdup (name), (gpointer) run_proc);
Elliot Lee's avatar
Elliot Lee committed
652 653
}

654 655 656
/**
 * gimp_uninstall_temp_proc:
 * @name: the procedure's name
657
 *
658 659 660
 * Uninstalls a temporary procedure which has previously been
 * installed using gimp_install_temp_proc().
 **/
Elliot Lee's avatar
Elliot Lee committed
661
void
662
gimp_uninstall_temp_proc (const gchar *name)
Elliot Lee's avatar
Elliot Lee committed
663 664
{
  GPProcUninstall proc_uninstall;
665 666 667 668 669 670
  gpointer        hash_name;
  gboolean        found;

  g_return_if_fail (name != NULL);

  proc_uninstall.name = (gchar *) name;
Elliot Lee's avatar
Elliot Lee committed
671

672
  if (! gp_proc_uninstall_write (_writechannel, &proc_uninstall, NULL))
Elliot Lee's avatar
Elliot Lee committed
673
    gimp_quit ();
674

Asbjørn Pettersen's avatar
Asbjørn Pettersen committed
675 676
  found = g_hash_table_lookup_extended (temp_proc_ht, name, &hash_name, NULL);
  if (found)
677 678
    {
      g_hash_table_remove (temp_proc_ht, (gpointer) name);
679
      g_free (hash_name);
680
    }
Elliot Lee's avatar
Elliot Lee committed
681 682
}

683 684 685 686
/**
 * gimp_run_procedure:
 * @name:          the name of the procedure to run
 * @n_return_vals: return location for the number of return values
687
 * @Varargs:       list of procedure parameters
688 689 690
 *
 * This function calls a GIMP procedure and returns its return values.
 *
Sven Neumann's avatar
Sven Neumann committed
691
 * The procedure's parameters are given by a va_list in the format
692 693 694 695 696 697 698
 * (type, value, type, value) and must be terminated by #GIMP_PDB_END.
 *
 * This function converts the va_list of parameters into an array
 * and passes them to gimp_run_procedure2().
 *
 * Return value: the procedure's return values.
 **/
699
GimpParam *
700 701
gimp_run_procedure (const gchar *name,
		    gint        *n_return_vals,
Elliot Lee's avatar
Elliot Lee committed
702 703
		    ...)
{
704 705
  GimpPDBArgType  param_type;
  GimpParam      *return_vals;
706 707
  GimpParam      *params   = NULL;
  gint            n_params = 0;
708 709
  va_list         args;
  gint            i;
Elliot Lee's avatar
Elliot Lee committed
710

711 712
  g_return_val_if_fail (name != NULL, NULL);
  g_return_val_if_fail (n_return_vals != NULL, NULL);
Elliot Lee's avatar
Elliot Lee committed
713

714
  va_start (args, n_return_vals);
715
  param_type = va_arg (args, GimpPDBArgType);
Elliot Lee's avatar
Elliot Lee committed
716

717
  while (param_type != GIMP_PDB_END)
Elliot Lee's avatar
Elliot Lee committed
718 719 720
    {
      switch (param_type)
	{
721 722 723 724 725 726 727 728 729 730
	case GIMP_PDB_INT32:
        case GIMP_PDB_DISPLAY:
        case GIMP_PDB_IMAGE:
        case GIMP_PDB_LAYER:
        case GIMP_PDB_CHANNEL:
        case GIMP_PDB_DRAWABLE:
        case GIMP_PDB_SELECTION:
        case GIMP_PDB_BOUNDARY:
        case GIMP_PDB_PATH:
        case GIMP_PDB_STATUS:
731
	  (void) va_arg (args, gint);
Elliot Lee's avatar
Elliot Lee committed
732
	  break;
733
	case GIMP_PDB_INT16:
734
	  (void) va_arg (args, gint);
Elliot Lee's avatar
Elliot Lee committed
735
	  break;
736
	case GIMP_PDB_INT8:
737
	  (void) va_arg (args, gint);
Elliot Lee's avatar
Elliot Lee committed
738
	  break;
739
        case GIMP_PDB_FLOAT:
740
          (void) va_arg (args, gdouble);
Elliot Lee's avatar
Elliot Lee committed
741
          break;
742
        case GIMP_PDB_STRING:
743
          (void) va_arg (args, gchar *);
Elliot Lee's avatar
Elliot Lee committed
744
          break;
745
        case GIMP_PDB_INT32ARRAY:
746
          (void) va_arg (args, gint32 *);
Elliot Lee's avatar
Elliot Lee committed
747
          break;
748
        case GIMP_PDB_INT16ARRAY:
749
          (void) va_arg (args, gint16 *);
Elliot Lee's avatar
Elliot Lee committed
750
          break;
751
        case GIMP_PDB_INT8ARRAY:
752
          (void) va_arg (args, gint8 *);
Elliot Lee's avatar
Elliot Lee committed
753
          break;
754
        case GIMP_PDB_FLOATARRAY:
755
          (void) va_arg (args, gdouble *);
Elliot Lee's avatar
Elliot Lee committed
756
          break;
757
        case GIMP_PDB_STRINGARRAY:
758
          (void) va_arg (args, gchar **);
Elliot Lee's avatar
Elliot Lee committed
759
          break;
760
        case GIMP_PDB_COLOR:
761
	  (void) va_arg (args, GimpRGB *);
Elliot Lee's avatar
Elliot Lee committed
762
          break;
763
        case GIMP_PDB_PARASITE:
764
          (void) va_arg (args, GimpParasite *);
765
          break;
766
        case GIMP_PDB_REGION:
Elliot Lee's avatar
Elliot Lee committed
767
          break;
768
	case GIMP_PDB_END:
Elliot Lee's avatar
Elliot Lee committed
769 770 771
	  break;
	}

772 773
      n_params++;

774
      param_type = va_arg (args, GimpPDBArgType);
Elliot Lee's avatar
Elliot Lee committed
775 776 777 778
    }

  va_end (args);

779
  params = g_new0 (GimpParam, n_params);
Elliot Lee's avatar
Elliot Lee committed
780

781
  va_start (args, n_return_vals);
Elliot Lee's avatar
Elliot Lee committed
782

783
  for (i = 0; i < n_params; i++)
Elliot Lee's avatar
Elliot Lee committed
784
    {
785
      params[i].type = va_arg (args, GimpPDBArgType);
Elliot Lee's avatar
Elliot Lee committed
786

787
      switch (params[i].type)
Elliot Lee's avatar
Elliot Lee committed
788
	{
789
	case GIMP_PDB_INT32:
790
	  params[i].data.d_int32 = (gint32) va_arg (args, gint);
Elliot Lee's avatar
Elliot Lee committed
791
	  break;
792
	case GIMP_PDB_INT16:
793
	  params[i].data.d_int16 = (gint16) va_arg (args, gint);
Elliot Lee's avatar
Elliot Lee committed
794
	  break;
795
	case GIMP_PDB_INT8:
796
	  params[i].data.d_int8 = (gint8) va_arg (args, gint);
Elliot Lee's avatar
Elliot Lee committed
797
	  break;
798
        case GIMP_PDB_FLOAT:
799
          params[i].data.d_float = (gdouble) va_arg (args, gdouble);
Elliot Lee's avatar
Elliot Lee committed
800
          break;
801
        case GIMP_PDB_STRING:
802
          params[i].data.d_string = va_arg (args, gchar *);
Elliot Lee's avatar
Elliot Lee committed
803
          break;
804
        case GIMP_PDB_INT32ARRAY:
805
          params[i].data.d_int32array = va_arg (args, gint32 *);
Elliot Lee's avatar
Elliot Lee committed
806
          break;
807
        case GIMP_PDB_INT16ARRAY:
808
          params[i].data.d_int16array = va_arg (args, gint16 *);
Elliot Lee's avatar
Elliot Lee committed
809
          break;
810
        case GIMP_PDB_INT8ARRAY:
811
          params[i].data.d_int8array = va_arg (args, gint8 *);
Elliot Lee's avatar
Elliot Lee committed
812
          break;
813
        case GIMP_PDB_FLOATARRAY:
814
          params[i].data.d_floatarray = va_arg (args, gdouble *);
Elliot Lee's avatar
Elliot Lee committed
815
          break;
816
        case GIMP_PDB_STRINGARRAY:
817
          params[i].data.d_stringarray = va_arg (args, gchar **);
Elliot Lee's avatar
Elliot Lee committed
818
          break;
819
        case GIMP_PDB_COLOR:
820
	  params[i].data.d_color = *va_arg (args, GimpRGB *);
Elliot Lee's avatar
Elliot Lee committed
821
          break;
822
        case GIMP_PDB_REGION:
Elliot Lee's avatar
Elliot Lee committed
823
          break;
824
        case GIMP_PDB_DISPLAY:
825
	  params[i].data.d_display = va_arg (args, gint32);
Elliot Lee's avatar
Elliot Lee committed
826
          break;
827
        case GIMP_PDB_IMAGE:
828
	  params[i].data.d_image = va_arg (args, gint32);
Elliot Lee's avatar
Elliot Lee committed
829
          break;
830
        case GIMP_PDB_LAYER:
831
	  params[i].data.d_layer = va_arg (args, gint32);
Elliot Lee's avatar
Elliot Lee committed
832
          break;
833
        case GIMP_PDB_CHANNEL:
834
	  params[i].data.d_channel = va_arg (args, gint32);
Elliot Lee's avatar
Elliot Lee committed
835
          break;
836
        case GIMP_PDB_DRAWABLE:
837
	  params[i].data.d_drawable = va_arg (args, gint32);
Elliot Lee's avatar
Elliot Lee committed
838
          break;
839
        case GIMP_PDB_SELECTION:
840
	  params[i].data.d_selection = va_arg (args, gint32);
Elliot Lee's avatar
Elliot Lee committed
841
          break;
842
        case GIMP_PDB_BOUNDARY:
843
	  params[i].data.d_boundary = va_arg (args, gint32);
Elliot Lee's avatar
Elliot Lee committed
844
          break;
845
        case GIMP_PDB_PATH:
846
	  params[i].data.d_path = va_arg (args, gint32);
Elliot Lee's avatar
Elliot Lee committed
847
          break;
848
        case GIMP_PDB_PARASITE:
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
          {
            GimpParasite *parasite = va_arg (args, GimpParasite *);

            if (parasite == NULL)
              {
                params[i].data.d_parasite.name = NULL;
                params[i].data.d_parasite.data = NULL;
              }
            else
              {
                params[i].data.d_parasite.name  = parasite->name;
                params[i].data.d_parasite.flags = parasite->flags;
                params[i].data.d_parasite.size  = parasite->size;
                params[i].data.d_parasite.data  = parasite->data;
              }
          }
          break;
866
        case GIMP_PDB_STATUS:
867
          params[i].data.d_status = va_arg (args, gint32);
Elliot Lee's avatar
Elliot Lee committed
868
          break;
869
	case GIMP_PDB_END:
Elliot Lee's avatar
Elliot Lee committed
870 871 872 873 874 875
	  break;
	}
    }

  va_end (args);

876 877
  return_vals = gimp_run_procedure2 (name, n_return_vals,
                                     n_params, params);
Elliot Lee's avatar
Elliot Lee committed
878

879
  g_free (params);
Elliot Lee's avatar
Elliot Lee committed
880 881 882 883

  return return_vals;
}

884
void
885
gimp_read_expect_msg (WireMessage *msg,
886
		      gint         type)
887
{
888
  while (TRUE)
889
    {
890
      if (! wire_read_msg (_readchannel, msg, NULL))
891
	gimp_quit ();
Michael Natterer's avatar