gimp.c 38.2 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"
65
#include "gimpimage.h"
Michael Natterer's avatar
Michael Natterer committed
66
#include "gimpimagefile.h"
67
#include "gimplist.h"
68
#include "gimpmarshal.h"
69
#include "gimppalette-load.h"
70 71
#include "gimppalette.h"
#include "gimpparasitelist.h"
72
#include "gimppattern-load.h"
73
#include "gimppattern.h"
74
#include "gimppatternclipboard.h"
Michael Natterer's avatar
Michael Natterer committed
75
#include "gimptagcache.h"
76
#include "gimptemplate.h"
77
#include "gimptoolinfo.h"
Alexia Death's avatar
Alexia Death committed
78 79
#include "gimptoolpreset.h"
#include "gimptoolpreset-load.h"
80

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


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


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

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

101 102 103 104 105 106
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);
107

108 109 110 111 112 113
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);
114 115


116
G_DEFINE_TYPE (Gimp, gimp, GIMP_TYPE_OBJECT)
117 118

#define parent_class gimp_parent_class
119

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

122 123 124 125

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

129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
  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,
145 146 147
                  gimp_marshal_VOID__POINTER,
                  G_TYPE_NONE, 1,
                  G_TYPE_POINTER);
148

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

159 160 161 162 163 164 165 166 167
  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);

168 169 170 171 172 173 174 175 176
  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);

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

  gimp_object_class->get_memsize = gimp_get_memsize;
181

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

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

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

203 204
  gimp->restored         = FALSE;

205
  gimp_gui_init (gimp);
206 207 208

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

210 211
  gimp_units_init (gimp);

212
  gimp->parasites           = gimp_parasite_list_new ();
213

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

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

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

221 222
  gimp->next_image_ID        = 1;
  gimp->next_guide_ID        = 1;
223
  gimp->next_sample_point_ID = 1;
224
  gimp->image_table          = g_hash_table_new (g_direct_hash, NULL);
225

226 227
  gimp->next_item_ID        = 1;
  gimp->item_table          = g_hash_table_new (g_direct_hash, NULL);
228

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

  gimp->next_display_ID     = 1;

238 239
  gimp->image_windows       = NULL;

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

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

253 254
  gimp->tag_cache           = NULL;

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

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

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

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

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

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

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

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

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

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

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

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

  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
300 301 302
  if (gimp->tool_preset_factory)
    gimp_data_factory_data_free (gimp->tool_preset_factory);

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

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

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

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

316 317 318 319 320 321 322 323 324 325 326 327
  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;
    }

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

334 335
  gimp_tool_info_set_standard (gimp, NULL);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

418
  if (gimp->item_table)
419
    {
420 421
      g_hash_table_destroy (gimp->item_table);
      gimp->item_table = NULL;
422 423 424 425 426 427 428 429
    }

  if (gimp->image_table)
    {
      g_hash_table_destroy (gimp->image_table);
      gimp->image_table = NULL;
    }

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

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

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

445
  gimp_paint_exit (gimp);
446

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

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

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

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

471
  gimp_units_exit (gimp);
472

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

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

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

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

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

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

495 496
  memsize += gimp_g_hash_table_get_memsize (gimp->image_table, 0);
  memsize += gimp_g_hash_table_get_memsize (gimp->item_table,  0);
497

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

500 501 502 503 504 505 506 507 508
  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);
509 510
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->dynamics_factory),
                                      gui_size);
511 512 513 514 515 516
  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
517 518
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->tool_preset_factory),
                                      gui_size);
519

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

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

525 526 527 528 529 530 531 532 533 534
  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);
535

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

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

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

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

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

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

  static const GimpDataFactoryLoaderEntry gradient_loader_entries[] =
  {
574 575 576
    { 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  }
577 578 579 580
  };

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

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

590
  GimpData *clipboard_brush;
591
  GimpData *clipboard_pattern;
592

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

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

598 599 600 601 602
  gimp_fonts_init (gimp);

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

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

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

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

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

Alexia Death's avatar
Alexia Death committed
655 656 657 658 659 660 661
  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,
662
                           NULL);
Alexia Death's avatar
Alexia Death committed
663 664 665
  gimp_object_set_static_name (GIMP_OBJECT (gimp->tool_preset_factory),
                               "tool preset factory");

666 667
  gimp->tag_cache = gimp_tag_cache_new ();

668 669 670
  gimp_paint_init (gimp);

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

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

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

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

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

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

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

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

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

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

  gimp->restored = TRUE;
717 718
}

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

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

729 730
  gimp_tag_cache_save (gimp->tag_cache);

731
  gimp_data_factory_data_save (gimp->brush_factory);
732
  gimp_data_factory_data_save (gimp->dynamics_factory);
733 734 735
  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
736 737
  gimp_data_factory_data_save (gimp->tool_preset_factory);

738
  gimp_fonts_reset (gimp);
739

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

  return FALSE; /* continue exiting */
}

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

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

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

767
  gimp->session_name     = g_strdup (session_name);
768 769
  gimp->be_verbose       = be_verbose       ? TRUE : FALSE;
  gimp->no_data          = no_data          ? TRUE : FALSE;
770
  gimp->no_fonts         = no_fonts         ? TRUE : FALSE;
771 772 773
  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
774
  gimp->stack_trace_mode = stack_trace_mode;
775
  gimp->pdb_compat_mode  = pdb_compat_mode;
Michael Natterer's avatar
Michael Natterer committed
776

777 778 779
  return gimp;
}

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 810
/**
 * 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;
}

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 857
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))
    {
858
      if (param_spec->flags & GIMP_CONFIG_PARAM_RESTART)
859
        {
Sven Neumann's avatar
Sven Neumann committed
860
#ifdef GIMP_CONFIG_DEBUG
861 862 863
          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
864
#endif
865 866 867
        }
      else
        {
Sven Neumann's avatar
Sven Neumann committed
868
#ifdef GIMP_CONFIG_DEBUG
869 870
          g_print ("Applying edit_config change of '%s' to global_config\n",
                   param_spec->name);
Sven Neumann's avatar
Sven Neumann committed
871
#endif
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
          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
889 890
gimp_load_config (Gimp        *gimp,
                  const gchar *alternate_system_gimprc,
891
                  const gchar *alternate_gimprc)
892
{
893 894
  GimpRc *gimprc;

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

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

  /*  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);
912

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

  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);
}

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

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

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

void
938
gimp_restore (Gimp               *gimp,
939
              GimpInitStatusFunc  status_callback)
940 941
{
  g_return_if_fail (GIMP_IS_GIMP (gimp));