gimp.c 38.1 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
Nate Summers's avatar
Nate Summers committed
2
 * Copyright (C) 1995-2002 Spencer Kimball, Peter Mattis, and others
3
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7 8 9 10 11 12 13 14
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 17 18 19
 */

#include "config.h"

Hans Breuer's avatar
updated  
Hans Breuer committed
20 21
#include <string.h> /* strlen */

22
#include <gegl.h>
23

24
#include "libgimpbase/gimpbase.h"
25
#include "libgimpconfig/gimpconfig.h"
26

27
#include "core-types.h"
28

29 30
#include "config/gimprc.h"

31 32
#include "pdb/gimppdb.h"
#include "pdb/gimp-pdb-compat.h"
33
#include "pdb/internal-procs.h"
34

35
#include "plug-in/gimppluginmanager.h"
36
#include "plug-in/gimppluginmanager-restore.h"
37

38
#include "paint/gimp-paint.h"
39

40
#include "text/gimp-fonts.h"
41

Michael Natterer's avatar
Michael Natterer committed
42 43
#include "xcf/xcf.h"

44
#include "gimp.h"
45
#include "gimp-contexts.h"
46
#include "gimp-gradients.h"
47
#include "gimp-modules.h"
48
#include "gimp-parasites.h"
49
#include "gimp-templates.h"
50
#include "gimp-units.h"
51
#include "gimp-utils.h"
52
#include "gimpbrush-load.h"
53
#include "gimpbrush.h"
54
#include "gimpbrushclipboard.h"
55
#include "gimpbrushgenerated-load.h"
56
#include "gimpbrushpipe-load.h"
57
#include "gimpbuffer.h"
Michael Natterer's avatar
Michael Natterer committed
58
#include "gimpcontext.h"
59
#include "gimpdatafactory.h"
Michael Natterer's avatar
Michael Natterer committed
60 61
#include "gimpdynamics.h"
#include "gimpdynamics-load.h"
62
#include "gimpdocumentlist.h"
63
#include "gimpgradient-load.h"
64
#include "gimpgradient.h"
Martin Nordholts's avatar
Martin Nordholts committed
65
#include "gimpidtable.h"
66
#include "gimpimage.h"
Michael Natterer's avatar
Michael Natterer committed
67
#include "gimpimagefile.h"
68
#include "gimplist.h"
69
#include "gimpmarshal.h"
70
#include "gimppalette-load.h"
71 72
#include "gimppalette.h"
#include "gimpparasitelist.h"
73
#include "gimppattern-load.h"
74
#include "gimppattern.h"
75
#include "gimppatternclipboard.h"
Michael Natterer's avatar
Michael Natterer committed
76
#include "gimptagcache.h"
77
#include "gimptemplate.h"
78
#include "gimptoolinfo.h"
Alexia Death's avatar
Alexia Death committed
79 80
#include "gimptoolpreset.h"
#include "gimptoolpreset-load.h"
81

82
#include "gimp-intl.h"
83 84


85 86
enum
{
87 88
  INITIALIZE,
  RESTORE,
89
  EXIT,
90
  BUFFER_CHANGED,
91
  IMAGE_OPENED,
92 93 94 95
  LAST_SIGNAL
};


96 97
static void      gimp_dispose              (GObject           *object);
static void      gimp_finalize             (GObject           *object);
98

99 100
static gint64    gimp_get_memsize          (GimpObject        *object,
                                            gint64            *gui_size);
101

102 103 104 105 106 107
static void      gimp_real_initialize      (Gimp              *gimp,
                                            GimpInitStatusFunc status_callback);
static void      gimp_real_restore         (Gimp              *gimp,
                                            GimpInitStatusFunc status_callback);
static gboolean  gimp_real_exit            (Gimp              *gimp,
                                            gboolean           force);
108

109 110 111 112 113 114
static void      gimp_global_config_notify (GObject           *global_config,
                                            GParamSpec        *param_spec,
                                            GObject           *edit_config);
static void      gimp_edit_config_notify   (GObject           *edit_config,
                                            GParamSpec        *param_spec,
                                            GObject           *global_config);
115 116


117
G_DEFINE_TYPE (Gimp, gimp, GIMP_TYPE_OBJECT)
118 119

#define parent_class gimp_parent_class
120

121 122
static guint gimp_signals[LAST_SIGNAL] = { 0, };

123 124 125 126

static void
gimp_class_init (GimpClass *klass)
{
127 128
  GObjectClass    *object_class      = G_OBJECT_CLASS (klass);
  GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
129

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
  gimp_signals[INITIALIZE] =
    g_signal_new ("initialize",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GimpClass, initialize),
                  NULL, NULL,
                  gimp_marshal_VOID__POINTER,
                  G_TYPE_NONE, 1,
                  G_TYPE_POINTER);

  gimp_signals[RESTORE] =
    g_signal_new ("restore",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GimpClass, restore),
                  NULL, NULL,
146 147 148
                  gimp_marshal_VOID__POINTER,
                  G_TYPE_NONE, 1,
                  G_TYPE_POINTER);
149

150 151 152 153 154
  gimp_signals[EXIT] =
    g_signal_new ("exit",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GimpClass, exit),
155
                  g_signal_accumulator_true_handled, NULL,
156 157 158 159
                  gimp_marshal_BOOLEAN__BOOLEAN,
                  G_TYPE_BOOLEAN, 1,
                  G_TYPE_BOOLEAN);

160 161 162 163 164 165 166 167 168
  gimp_signals[BUFFER_CHANGED] =
    g_signal_new ("buffer-changed",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GimpClass, buffer_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);

169 170 171 172 173 174 175 176 177
  gimp_signals[IMAGE_OPENED] =
    g_signal_new ("image-opened",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GimpClass, image_opened),
                  NULL, NULL,
                  gimp_marshal_VOID__STRING,
                  G_TYPE_NONE, 1, G_TYPE_STRING);

178 179 180 181
  object_class->dispose          = gimp_dispose;
  object_class->finalize         = gimp_finalize;

  gimp_object_class->get_memsize = gimp_get_memsize;
182

183 184
  klass->initialize              = gimp_real_initialize;
  klass->restore                 = gimp_real_restore;
185
  klass->exit                    = gimp_real_exit;
186
  klass->buffer_changed          = NULL;
187 188 189 190 191
}

static void
gimp_init (Gimp *gimp)
{
192 193
  gimp->config           = NULL;
  gimp->session_name     = NULL;
194 195 196 197

  gimp->be_verbose       = FALSE;
  gimp->no_data          = FALSE;
  gimp->no_interface     = FALSE;
198
  gimp->show_gui         = TRUE;
199 200 201
  gimp->use_shm          = FALSE;
  gimp->message_handler  = GIMP_CONSOLE;
  gimp->stack_trace_mode = GIMP_STACK_TRACE_NEVER;
202
  gimp->pdb_compat_mode  = GIMP_PDB_COMPAT_OFF;
203

204 205
  gimp->restored         = FALSE;

206
  gimp_gui_init (gimp);
207 208 209

  gimp->busy                = 0;
  gimp->busy_idle_id        = 0;
210

211 212
  gimp_units_init (gimp);

213
  gimp->parasites           = gimp_parasite_list_new ();
214

Michael Natterer's avatar
Michael Natterer committed
215
  gimp_modules_init (gimp);
216

217
  gimp->plug_in_manager     = gimp_plug_in_manager_new (gimp);
Michael Natterer's avatar
Michael Natterer committed
218

219
  gimp->images              = gimp_list_new_weak (GIMP_TYPE_IMAGE, FALSE);
220
  gimp_object_set_static_name (GIMP_OBJECT (gimp->images), "images");
221

222
  gimp->next_guide_ID        = 1;
223
  gimp->next_sample_point_ID = 1;
Martin Nordholts's avatar
Martin Nordholts committed
224
  gimp->image_table          = gimp_id_table_new ();
225

Martin Nordholts's avatar
Martin Nordholts committed
226
  gimp->item_table          = gimp_id_table_new ();
227

228 229 230 231 232
  gimp->displays            = g_object_new (GIMP_TYPE_LIST,
                                            "children-type", GIMP_TYPE_OBJECT,
                                            "policy",        GIMP_CONTAINER_POLICY_WEAK,
                                            "append",        TRUE,
                                            NULL);
233
  gimp_object_set_static_name (GIMP_OBJECT (gimp->displays), "displays");
234 235 236

  gimp->next_display_ID     = 1;

237 238
  gimp->image_windows       = NULL;

239
  gimp->global_buffer       = NULL;
240
  gimp->named_buffers       = gimp_list_new (GIMP_TYPE_BUFFER, TRUE);
241 242
  gimp_object_set_static_name (GIMP_OBJECT (gimp->named_buffers),
                               "named buffers");
243

244
  gimp->fonts               = NULL;
245
  gimp->brush_factory       = NULL;
246
  gimp->dynamics_factory    = NULL;
247 248 249
  gimp->pattern_factory     = NULL;
  gimp->gradient_factory    = NULL;
  gimp->palette_factory     = NULL;
Alexia Death's avatar
Alexia Death committed
250 251
  gimp->tool_preset_factory = NULL;

252 253
  gimp->tag_cache           = NULL;

254
  gimp->pdb                 = gimp_pdb_new (gimp);
255

Michael Natterer's avatar
Michael Natterer committed
256 257
  xcf_init (gimp);

258
  gimp->tool_info_list      = gimp_list_new (GIMP_TYPE_TOOL_INFO, FALSE);
259 260
  gimp_object_set_static_name (GIMP_OBJECT (gimp->tool_info_list),
                               "tool infos");
261

262
  gimp->standard_tool_info  = NULL;
Michael Natterer's avatar
Michael Natterer committed
263

264
  gimp->documents           = gimp_document_list_new (gimp);
Michael Natterer's avatar
Michael Natterer committed
265

266
  gimp->templates           = gimp_list_new (GIMP_TYPE_TEMPLATE, TRUE);
267
  gimp_object_set_static_name (GIMP_OBJECT (gimp->templates), "templates");
268

269
  gimp->image_new_last_template = NULL;
Michael Natterer's avatar
Michael Natterer committed
270

271 272 273
  gimp->context_list        = NULL;
  gimp->default_context     = NULL;
  gimp->user_context        = NULL;
274 275 276
}

static void
277 278
gimp_dispose (GObject *object)
{
279
  Gimp *gimp = GIMP (object);
280

281 282 283 284 285
  if (gimp->be_verbose)
    g_print ("EXIT: %s\n", G_STRFUNC);

  if (gimp->brush_factory)
    gimp_data_factory_data_free (gimp->brush_factory);
286

287 288
  if (gimp->dynamics_factory)
    gimp_data_factory_data_free (gimp->dynamics_factory);
289 290 291 292 293 294 295 296 297 298

  if (gimp->pattern_factory)
    gimp_data_factory_data_free (gimp->pattern_factory);

  if (gimp->gradient_factory)
    gimp_data_factory_data_free (gimp->gradient_factory);

  if (gimp->palette_factory)
    gimp_data_factory_data_free (gimp->palette_factory);

Alexia Death's avatar
Alexia Death committed
299 300 301
  if (gimp->tool_preset_factory)
    gimp_data_factory_data_free (gimp->tool_preset_factory);

302 303 304 305 306 307 308 309
  G_OBJECT_CLASS (parent_class)->dispose (object);
}

static void
gimp_finalize (GObject *object)
{
  Gimp *gimp = GIMP (object);

310
  if (gimp->be_verbose)
311
    g_print ("EXIT: %s\n", G_STRFUNC);
312

313
  gimp_contexts_exit (gimp);
Michael Natterer's avatar
Michael Natterer committed
314

315 316 317 318 319 320 321 322 323 324 325 326
  if (gimp->image_new_last_template)
    {
      g_object_unref (gimp->image_new_last_template);
      gimp->image_new_last_template = NULL;
    }

  if (gimp->templates)
    {
      g_object_unref (gimp->templates);
      gimp->templates = NULL;
    }

327
  if (gimp->documents)
328
    {
329
      g_object_unref (gimp->documents);
330 331
      gimp->documents = NULL;
    }
Michael Natterer's avatar
Michael Natterer committed
332

333 334
  gimp_tool_info_set_standard (gimp, NULL);

335 336
  if (gimp->tool_info_list)
    {
337 338
      gimp_container_foreach (gimp->tool_info_list,
                              (GFunc) g_object_run_dispose, NULL);
339
      g_object_unref (gimp->tool_info_list);
340 341 342
      gimp->tool_info_list = NULL;
    }

Michael Natterer's avatar
Michael Natterer committed
343 344
  xcf_exit (gimp);

345 346 347 348 349
  if (gimp->pdb)
    {
      g_object_unref (gimp->pdb);
      gimp->pdb = NULL;
    }
Michael Natterer's avatar
Michael Natterer committed
350

351 352
  if (gimp->brush_factory)
    {
353
      g_object_unref (gimp->brush_factory);
354 355 356
      gimp->brush_factory = NULL;
    }

357 358 359 360 361 362
  if (gimp->dynamics_factory)
    {
      g_object_unref (gimp->dynamics_factory);
      gimp->dynamics_factory = NULL;
    }

363 364
  if (gimp->pattern_factory)
    {
365
      g_object_unref (gimp->pattern_factory);
366 367 368 369 370
      gimp->pattern_factory = NULL;
    }

  if (gimp->gradient_factory)
    {
371
      g_object_unref (gimp->gradient_factory);
372 373 374 375 376
      gimp->gradient_factory = NULL;
    }

  if (gimp->palette_factory)
    {
377
      g_object_unref (gimp->palette_factory);
378 379 380
      gimp->palette_factory = NULL;
    }

Alexia Death's avatar
Alexia Death committed
381 382 383 384 385 386
  if (gimp->tool_preset_factory)
    {
      g_object_unref (gimp->tool_preset_factory);
      gimp->tool_preset_factory = NULL;
    }

387 388 389 390 391 392
  if (gimp->tag_cache)
    {
      g_object_unref (gimp->tag_cache);
      gimp->tag_cache = NULL;
    }

393 394 395 396 397 398
  if (gimp->fonts)
    {
      g_object_unref (gimp->fonts);
      gimp->fonts = NULL;
    }

399 400
  if (gimp->named_buffers)
    {
401
      g_object_unref (gimp->named_buffers);
402 403 404 405 406
      gimp->named_buffers = NULL;
    }

  if (gimp->global_buffer)
    {
407
      g_object_unref (gimp->global_buffer);
408 409 410
      gimp->global_buffer = NULL;
    }

411 412 413 414 415 416
  if (gimp->displays)
    {
      g_object_unref (gimp->displays);
      gimp->displays = NULL;
    }

417
  if (gimp->item_table)
418
    {
Martin Nordholts's avatar
Martin Nordholts committed
419
      g_object_unref (gimp->item_table);
420
      gimp->item_table = NULL;
421 422 423 424
    }

  if (gimp->image_table)
    {
Martin Nordholts's avatar
Martin Nordholts committed
425
      g_object_unref (gimp->image_table);
426 427 428
      gimp->image_table = NULL;
    }

429 430
  if (gimp->images)
    {
431
      g_object_unref (gimp->images);
432 433 434
      gimp->images = NULL;
    }

435
  if (gimp->plug_in_manager)
436
    {
437 438
      g_object_unref (gimp->plug_in_manager);
      gimp->plug_in_manager = NULL;
439 440
    }

441
  if (gimp->module_db)
Michael Natterer's avatar
Michael Natterer committed
442 443
    gimp_modules_exit (gimp);

444
  gimp_paint_exit (gimp);
445

446
  if (gimp->parasites)
Sven Neumann's avatar
Sven Neumann committed
447
    {
448
      g_object_unref (gimp->parasites);
Sven Neumann's avatar
Sven Neumann committed
449 450
      gimp->parasites = NULL;
    }
451

452 453 454 455 456 457
  if (gimp->edit_config)
    {
      g_object_unref (gimp->edit_config);
      gimp->edit_config = NULL;
    }

458 459 460 461 462 463
  if (gimp->session_name)
    {
      g_free (gimp->session_name);
      gimp->session_name = NULL;
    }

Sven Neumann's avatar
Sven Neumann committed
464 465 466 467 468 469
  if (gimp->context_list)
    {
      g_list_free (gimp->context_list);
      gimp->context_list = NULL;
    }

470
  gimp_units_exit (gimp);
471

472
  G_OBJECT_CLASS (parent_class)->finalize (object);
473 474
}

475
static gint64
476
gimp_get_memsize (GimpObject *object,
477
                  gint64     *gui_size)
478
{
479
  Gimp   *gimp    = GIMP (object);
480
  gint64  memsize = 0;
481

482
  memsize += gimp_g_list_get_memsize (gimp->user_units, 0 /* FIXME */);
483

484 485
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->parasites),
                                      gui_size);
486

487 488 489
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->paint_info_list),
                                      gui_size);

490
  memsize += gimp_g_object_get_memsize (G_OBJECT (gimp->module_db));
491 492
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->plug_in_manager),
                                      gui_size);
493

Martin Nordholts's avatar
Martin Nordholts committed
494 495
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->image_table), 0);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->item_table),  0);
496

497
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->displays), gui_size);
498

499 500 501 502 503 504 505 506 507
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->global_buffer),
                                      gui_size);

  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->named_buffers),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->fonts),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->brush_factory),
                                      gui_size);
508 509
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->dynamics_factory),
                                      gui_size);
510 511 512 513 514 515
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->pattern_factory),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->gradient_factory),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->palette_factory),
                                      gui_size);
Alexia Death's avatar
Alexia Death committed
516 517
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->tool_preset_factory),
                                      gui_size);
518

519 520 521
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->tag_cache),
                                      gui_size);

522
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->pdb), gui_size);
523

524 525 526 527 528 529 530 531 532 533
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->tool_info_list),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->standard_tool_info),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->documents),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->templates),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->image_new_last_template),
                                      gui_size);
534

535
  memsize += gimp_g_list_get_memsize (gimp->context_list, 0);
536

537 538 539 540
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->default_context),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->user_context),
                                      gui_size);
541

542 543
  return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
                                                                  gui_size);
544 545
}

546 547 548 549 550 551
static void
gimp_real_initialize (Gimp               *gimp,
                      GimpInitStatusFunc  status_callback)
{
  static const GimpDataFactoryLoaderEntry brush_loader_entries[] =
  {
552 553
    { gimp_brush_load,           GIMP_BRUSH_FILE_EXTENSION,           FALSE },
    { gimp_brush_load,           GIMP_BRUSH_PIXMAP_FILE_EXTENSION,    FALSE },
554 555
    { gimp_brush_load_abr,       GIMP_BRUSH_PS_FILE_EXTENSION,        FALSE },
    { gimp_brush_load_abr,       GIMP_BRUSH_PSP_FILE_EXTENSION,       FALSE },
556 557
    { gimp_brush_generated_load, GIMP_BRUSH_GENERATED_FILE_EXTENSION, TRUE  },
    { gimp_brush_pipe_load,      GIMP_BRUSH_PIPE_FILE_EXTENSION,      FALSE }
558 559
  };

560 561
  static const GimpDataFactoryLoaderEntry dynamics_loader_entries[] =
  {
Michael Natterer's avatar
Michael Natterer committed
562
    { gimp_dynamics_load,        GIMP_DYNAMICS_FILE_EXTENSION,        TRUE  }
563
  };
564

565 566
  static const GimpDataFactoryLoaderEntry pattern_loader_entries[] =
  {
567 568
    { gimp_pattern_load,         GIMP_PATTERN_FILE_EXTENSION,         FALSE },
    { gimp_pattern_load_pixbuf,  NULL,                                FALSE }
569 570 571 572
  };

  static const GimpDataFactoryLoaderEntry gradient_loader_entries[] =
  {
573 574 575
    { gimp_gradient_load,        GIMP_GRADIENT_FILE_EXTENSION,        TRUE  },
    { gimp_gradient_load_svg,    GIMP_GRADIENT_SVG_FILE_EXTENSION,    FALSE },
    { gimp_gradient_load,        NULL /* legacy loader */,            TRUE  }
576 577 578 579
  };

  static const GimpDataFactoryLoaderEntry palette_loader_entries[] =
  {
580 581
    { gimp_palette_load,         GIMP_PALETTE_FILE_EXTENSION,         TRUE  },
    { gimp_palette_load,         NULL /* legacy loader */,            TRUE  }
582 583
  };

Alexia Death's avatar
Alexia Death committed
584 585
  static const GimpDataFactoryLoaderEntry tool_preset_loader_entries[] =
  {
586
    { gimp_tool_preset_load,     GIMP_TOOL_PRESET_FILE_EXTENSION,     TRUE  }
Alexia Death's avatar
Alexia Death committed
587 588
  };

589
  GimpData *clipboard_brush;
590
  GimpData *clipboard_pattern;
591

592
  if (gimp->be_verbose)
593
    g_print ("INIT: %s\n", G_STRFUNC);
594

595 596
  status_callback (_("Initialization"), NULL, 0.0);

597 598 599 600 601
  gimp_fonts_init (gimp);

  gimp->brush_factory =
    gimp_data_factory_new (gimp,
                           GIMP_TYPE_BRUSH,
602 603 604 605 606
                           "brush-path", "brush-path-writable",
                           brush_loader_entries,
                           G_N_ELEMENTS (brush_loader_entries),
                           gimp_brush_new,
                           gimp_brush_get_standard);
607 608
  gimp_object_set_static_name (GIMP_OBJECT (gimp->brush_factory),
                               "brush factory");
609

610 611
  gimp->dynamics_factory =
    gimp_data_factory_new (gimp,
612
                           GIMP_TYPE_DYNAMICS,
613
                           "dynamics-path", "dynamics-path-writable",
614 615
                           dynamics_loader_entries,
                           G_N_ELEMENTS (dynamics_loader_entries),
616
                           gimp_dynamics_new,
617 618 619 620
                           gimp_dynamics_get_standard);
  gimp_object_set_static_name (GIMP_OBJECT (gimp->dynamics_factory),
                               "dynamics factory");

621 622 623
  gimp->pattern_factory =
    gimp_data_factory_new (gimp,
                           GIMP_TYPE_PATTERN,
624 625 626 627 628
                           "pattern-path", "pattern-path-writable",
                           pattern_loader_entries,
                           G_N_ELEMENTS (pattern_loader_entries),
                           NULL,
                           gimp_pattern_get_standard);
629 630
  gimp_object_set_static_name (GIMP_OBJECT (gimp->pattern_factory),
                               "pattern factory");
631 632 633 634

  gimp->gradient_factory =
    gimp_data_factory_new (gimp,
                           GIMP_TYPE_GRADIENT,
635 636 637 638 639
                           "gradient-path", "gradient-path-writable",
                           gradient_loader_entries,
                           G_N_ELEMENTS (gradient_loader_entries),
                           gimp_gradient_new,
                           gimp_gradient_get_standard);
640 641
  gimp_object_set_static_name (GIMP_OBJECT (gimp->gradient_factory),
                               "gradient factory");
642 643 644 645

  gimp->palette_factory =
    gimp_data_factory_new (gimp,
                           GIMP_TYPE_PALETTE,
646 647 648 649 650
                           "palette-path", "palette-path-writable",
                           palette_loader_entries,
                           G_N_ELEMENTS (palette_loader_entries),
                           gimp_palette_new,
                           gimp_palette_get_standard);
651 652
  gimp_object_set_static_name (GIMP_OBJECT (gimp->palette_factory),
                               "palette factory");
653

Alexia Death's avatar
Alexia Death committed
654 655 656 657 658 659 660
  gimp->tool_preset_factory =
    gimp_data_factory_new (gimp,
                           GIMP_TYPE_TOOL_PRESET,
                           "tool-preset-path", "tool-preset-path-writable",
                           tool_preset_loader_entries,
                           G_N_ELEMENTS (tool_preset_loader_entries),
                           gimp_tool_preset_new,
661
                           NULL);
Alexia Death's avatar
Alexia Death committed
662 663 664
  gimp_object_set_static_name (GIMP_OBJECT (gimp->tool_preset_factory),
                               "tool preset factory");

665 666
  gimp->tag_cache = gimp_tag_cache_new ();

667 668 669
  gimp_paint_init (gimp);

  /* Set the last values used to default values. */
670 671
  gimp->image_new_last_template =
    gimp_config_duplicate (GIMP_CONFIG (gimp->config->default_image));
672

673 674
  /*  create user and default context  */
  gimp_contexts_init (gimp);
675 676 677 678

  /*  add the builtin FG -> BG etc. gradients  */
  gimp_gradients_init (gimp);

679 680
  /*  add the clipboard brush  */
  clipboard_brush = gimp_brush_clipboard_new (gimp);
681 682
  gimp_data_make_internal (GIMP_DATA (clipboard_brush),
                           "gimp-brush-clipboard");
683
  gimp_container_add (gimp_data_factory_get_container (gimp->brush_factory),
684 685 686
                      GIMP_OBJECT (clipboard_brush));
  g_object_unref (clipboard_brush);

687 688
  /*  add the clipboard pattern  */
  clipboard_pattern = gimp_pattern_clipboard_new (gimp);
689 690
  gimp_data_make_internal (GIMP_DATA (clipboard_pattern),
                           "gimp-pattern-clipboard");
691
  gimp_container_add (gimp_data_factory_get_container (gimp->pattern_factory),
692 693 694
                      GIMP_OBJECT (clipboard_pattern));
  g_object_unref (clipboard_pattern);

695
  /*  register all internal procedures  */
Sven Neumann's avatar
Sven Neumann committed
696
  status_callback (NULL, _("Internal Procedures"), 0.2);
697 698
  internal_procs_init (gimp->pdb);
  gimp_pdb_compat_procs_register (gimp->pdb, gimp->pdb_compat_mode);
699

700
  gimp_plug_in_manager_initialize (gimp->plug_in_manager, status_callback);
701 702

  status_callback (NULL, "", 1.0);
703 704 705 706
}

static void
gimp_real_restore (Gimp               *gimp,
707
                   GimpInitStatusFunc  status_callback)
708 709
{
  if (gimp->be_verbose)
710
    g_print ("INIT: %s\n", G_STRFUNC);
711

712 713
  gimp_plug_in_manager_restore (gimp->plug_in_manager,
                                gimp_get_user_context (gimp), status_callback);
714 715

  gimp->restored = TRUE;
716 717
}

718 719
static gboolean
gimp_real_exit (Gimp     *gimp,
720
                gboolean  force)
721
{
722
  if (gimp->be_verbose)
723
    g_print ("EXIT: %s\n", G_STRFUNC);
724

725
  gimp_plug_in_manager_exit (gimp->plug_in_manager);
726
  gimp_modules_unload (gimp);
727

728 729
  gimp_tag_cache_save (gimp->tag_cache);

730
  gimp_data_factory_data_save (gimp->brush_factory);
731
  gimp_data_factory_data_save (gimp->dynamics_factory);
732 733 734
  gimp_data_factory_data_save (gimp->pattern_factory);
  gimp_data_factory_data_save (gimp->gradient_factory);
  gimp_data_factory_data_save (gimp->palette_factory);
Alexia Death's avatar
Alexia Death committed
735 736
  gimp_data_factory_data_save (gimp->tool_preset_factory);

737
  gimp_fonts_reset (gimp);
738

739
  gimp_templates_save (gimp);
740 741 742 743 744 745
  gimp_parasiterc_save (gimp);
  gimp_unitrc_save (gimp);

  return FALSE; /* continue exiting */
}

746
Gimp *
747
gimp_new (const gchar       *name,
748
          const gchar       *session_name,
749
          gboolean           be_verbose,
Michael Natterer's avatar
Michael Natterer committed
750
          gboolean           no_data,
751
          gboolean           no_fonts,
Michael Natterer's avatar
Michael Natterer committed
752
          gboolean           no_interface,
753
          gboolean           use_shm,
754
          gboolean           console_messages,
755 756
          GimpStackTraceMode stack_trace_mode,
          GimpPDBCompatMode  pdb_compat_mode)
757 758 759
{
  Gimp *gimp;

760 761
  g_return_val_if_fail (name != NULL, NULL);

762
  gimp = g_object_new (GIMP_TYPE_GIMP,
763
                       "name", name,
764
                       NULL);
765

766
  gimp->session_name     = g_strdup (session_name);
767 768
  gimp->be_verbose       = be_verbose       ? TRUE : FALSE;
  gimp->no_data          = no_data          ? TRUE : FALSE;
769
  gimp->no_fonts         = no_fonts         ? TRUE : FALSE;
770 771 772
  gimp->no_interface     = no_interface     ? TRUE : FALSE;
  gimp->use_shm          = use_shm          ? TRUE : FALSE;
  gimp->console_messages = console_messages ? TRUE : FALSE;
Michael Natterer's avatar
Michael Natterer committed
773
  gimp->stack_trace_mode = stack_trace_mode;
774
  gimp->pdb_compat_mode  = pdb_compat_mode;
Michael Natterer's avatar
Michael Natterer committed
775

776 777 778
  return gimp;
}

779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
/**
 * gimp_set_show_gui:
 * @gimp:
 * @show:
 *
 * Test cases that tests the UI typically don't want any windows to be
 * presented during the test run. Allow them to set this.
 **/
void
gimp_set_show_gui (Gimp     *gimp,
                   gboolean  show_gui)
{
  g_return_if_fail (GIMP_IS_GIMP (gimp));

  gimp->show_gui = show_gui;
}

/**
 * gimp_get_show_gui:
 * @gimp:
 *
 * Returns: %TRUE if the GUI should be shown, %FALSE otherwise.
 **/
gboolean
gimp_get_show_gui (Gimp *gimp)
{
  g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);

  return gimp->show_gui;
}

810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856
static void
gimp_global_config_notify (GObject    *global_config,
                           GParamSpec *param_spec,
                           GObject    *edit_config)
{
  GValue global_value = { 0, };
  GValue edit_value   = { 0, };

  g_value_init (&global_value, param_spec->value_type);
  g_value_init (&edit_value,   param_spec->value_type);

  g_object_get_property (global_config, param_spec->name, &global_value);
  g_object_get_property (edit_config,   param_spec->name, &edit_value);

  if (g_param_values_cmp (param_spec, &global_value, &edit_value))
    {
      g_signal_handlers_block_by_func (edit_config,
                                       gimp_edit_config_notify,
                                       global_config);

      g_object_set_property (edit_config, param_spec->name, &global_value);

      g_signal_handlers_unblock_by_func (edit_config,
                                         gimp_edit_config_notify,
                                         global_config);
    }

  g_value_unset (&global_value);
  g_value_unset (&edit_value);
}

static void
gimp_edit_config_notify (GObject    *edit_config,
                         GParamSpec *param_spec,
                         GObject    *global_config)
{
  GValue edit_value   = { 0, };
  GValue global_value = { 0, };

  g_value_init (&edit_value,   param_spec->value_type);
  g_value_init (&global_value, param_spec->value_type);

  g_object_get_property (edit_config,   param_spec->name, &edit_value);
  g_object_get_property (global_config, param_spec->name, &global_value);

  if (g_param_values_cmp (param_spec, &edit_value, &global_value))
    {
857
      if (param_spec->flags & GIMP_CONFIG_PARAM_RESTART)
858
        {
Sven Neumann's avatar
Sven Neumann committed
859
#ifdef GIMP_CONFIG_DEBUG
860 861 862
          g_print ("NOT Applying edit_config change of '%s' to global_config "
                   "because it needs restart\n",
                   param_spec->name);
Sven Neumann's avatar
Sven Neumann committed
863
#endif
864 865 866
        }
      else
        {
Sven Neumann's avatar
Sven Neumann committed
867
#ifdef GIMP_CONFIG_DEBUG
868 869
          g_print ("Applying edit_config change of '%s' to global_config\n",
                   param_spec->name);
Sven Neumann's avatar
Sven Neumann committed
870
#endif
871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
          g_signal_handlers_block_by_func (global_config,
                                           gimp_global_config_notify,
                                           edit_config);

          g_object_set_property (global_config, param_spec->name, &edit_value);

          g_signal_handlers_unblock_by_func (global_config,
                                             gimp_global_config_notify,
                                             edit_config);
        }
    }

  g_value_unset (&edit_value);
  g_value_unset (&global_value);
}

void
888 889
gimp_load_config (Gimp        *gimp,
                  const gchar *alternate_system_gimprc,
890
                  const gchar *alternate_gimprc)
891
{
892 893
  GimpRc *gimprc;

894 895 896 897
  g_return_if_fail (GIMP_IS_GIMP (gimp));
  g_return_if_fail (gimp->config == NULL);
  g_return_if_fail (gimp->edit_config == NULL);

898
  if (gimp->be_verbose)
899
    g_print ("INIT: %s\n", G_STRFUNC);
900 901 902 903 904 905 906 907 908 909 910

  /*  this needs to be done before gimprc loading because gimprc can
   *  use user defined units
   */
  gimp_unitrc_load (gimp);

  gimprc = gimp_rc_new (alternate_system_gimprc,
                        alternate_gimprc,
                        gimp->be_verbose);

  gimp->config = GIMP_CORE_CONFIG (gimprc);
911

912
  gimp->edit_config = gimp_config_duplicate (GIMP_CONFIG (gimp->config));
913 914 915 916 917 918 919 920 921

  g_signal_connect_object (gimp->config, "notify",
                           G_CALLBACK (gimp_global_config_notify),
                           gimp->edit_config, 0);
  g_signal_connect_object (gimp->edit_config, "notify",
                           G_CALLBACK (gimp_edit_config_notify),
                           gimp->config, 0);
}

922
void
923 924
gimp_initialize (Gimp               *gimp,
                 GimpInitStatusFunc  status_callback)
925 926
{
  g_return_if_fail (GIMP_IS_GIMP (gimp));
927
  g_return_if_fail (status_callback != NULL);
928
  g_return_if_fail (GIMP_IS_CORE_CONFIG (gimp->config));
929

930
  if (gimp->be_verbose)
931
    g_print ("INIT: %s\n", G_STRFUNC);
932

933
  g_signal_emit (gimp, gimp_signals[INITIALIZE], 0, status_callback);
934 935 936
}

void
937
gimp_restore (Gimp               *gimp,
Sven Neumann's avatar